Enhance internship application process: update InternshipsPageController to retrieve internships and validate application submissions, modify Internship model to include relationships, and implement dynamic application modals in views for internships and careers. Update Livewire configuration for improved file upload handling.

This commit is contained in:
2025-07-29 12:37:25 +05:00
parent 9603402fee
commit f6ddf1d9c1
18 changed files with 986 additions and 119 deletions

View File

@@ -0,0 +1,125 @@
<?php
namespace App\Filament\Resources;
use App\Filament\Resources\InternshipResource\Pages;
use App\Filament\Resources\InternshipResource\RelationManagers;
use App\Models\Internship;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Textarea;
class InternshipResource extends Resource
{
protected static ?string $model = Internship::class;
protected static ?string $navigationGroup = 'Internships';
protected static ?string $navigationIcon = 'heroicon-o-academic-cap';
public static function form(Form $form): Form
{
return $form
->schema([
TextInput::make('title')
->required()
->maxLength(255),
TextInput::make('location')
->required()
->maxLength(255),
Textarea::make('title_description')
->label('Description (show on modal)')
->required()
->maxLength(65535)
->columnSpan('full'),
TextInput::make('salary_per_month')
->required()
->numeric()
->label('Salary per month')
->maxLength(255),
Forms\Components\Select::make('salary_currency')
->options(getCurrencies())
->required()
->label('Salary currency')
->searchable()
->default('USD'),
Repeater::make('bullets')
->schema([
TextInput::make('bullet')
->required()
->maxLength(255),
])
->minItems(1)
->defaultItems(1)
->columnSpan('full'),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('title')
->searchable(),
Tables\Columns\TextColumn::make('title_description')
->searchable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('salary_per_month')
->searchable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('salary_currency')
->searchable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('location')
->searchable(),
Tables\Columns\TextColumn::make('salary')
->searchable(),
Tables\Columns\TextColumn::make('created_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('updated_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}
public static function getRelations(): array
{
return [
RelationManagers\ApplicationsRelationManager::class,
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListInternships::route('/'),
'create' => Pages\CreateInternship::route('/create'),
'edit' => Pages\EditInternship::route('/{record}/edit'),
];
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace App\Filament\Resources\InternshipResource\Pages;
use App\Filament\Resources\InternshipResource;
use Filament\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateInternship extends CreateRecord
{
protected static string $resource = InternshipResource::class;
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\InternshipResource\Pages;
use App\Filament\Resources\InternshipResource;
use Filament\Actions;
use Filament\Resources\Pages\EditRecord;
class EditInternship extends EditRecord
{
protected static string $resource = InternshipResource::class;
protected function getHeaderActions(): array
{
return [
Actions\DeleteAction::make(),
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\InternshipResource\Pages;
use App\Filament\Resources\InternshipResource;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;
class ListInternships extends ListRecords
{
protected static string $resource = InternshipResource::class;
protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),
];
}
}

View File

@@ -0,0 +1,83 @@
<?php
namespace App\Filament\Resources\InternshipResource\RelationManagers;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\RelationManagers\RelationManager;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use App\Models\InternshipApplication; // Added this use statement
class ApplicationsRelationManager extends RelationManager
{
protected static string $relationship = 'applications';
// Add this line to define the inverse relationship
protected static ?string $model = InternshipApplication::class;
public function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('name')
->required()
->maxLength(255),
Forms\Components\DatePicker::make('birthdate')
->required(),
Forms\Components\FileUpload::make('resume_file')
->required()
->acceptedFileTypes(['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'])
->disk('public') // or your preferred disk
->directory('resumes'),
Forms\Components\TextInput::make('email')
->email()
->required()
->maxLength(255),
Forms\Components\TextInput::make('phone_number')
->required()
->maxLength(20),
Forms\Components\Textarea::make('cover_letter')
->maxLength(65535)
->nullable()
->columnSpan('full'),
]);
}
public function table(Table $table): Table
{
return $table
->recordTitleAttribute('name')
->columns([
Tables\Columns\TextColumn::make('name')
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('email')
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('phone_number')
->searchable(),
Tables\Columns\TextColumn::make('created_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
//
])
->headerActions([
Tables\Actions\CreateAction::make(),
])
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\DeleteAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}
}

View File

@@ -4,17 +4,44 @@ namespace App\Http\Controllers;
use App\Models\Internship;
use Illuminate\Http\Request;
use App\Models\InternshipApplication; // Changed from App\Models\Application
class InternshipsPageController extends Controller
{
public function index()
{
return view('web.pages.internships.index');
$internships = Internship::query()->get();
return view('web.pages.internships.index', compact('internships'));
}
public function store(Request $request)
{
dd($request->all());
$validatedData = $request->validate([
'internship_id' => 'required|exists:internships,id',
'name' => 'required|string|max:255',
'birthdate' => 'required|date',
'resume_file' => 'required|file|mimes:pdf,doc,docx|max:2048',
'email' => 'required|email|max:255',
'phone_number' => 'required|string',
'cover_letter' => 'nullable|string',
]);
$resumePath = $request->file('resume_file')->store('resumes');
InternshipApplication::create([ // Changed to InternshipApplication::create
'internship_id' => $validatedData['internship_id'],
'name' => $validatedData['name'],
'birthdate' => $validatedData['birthdate'],
'resume_file' => $resumePath,
'email' => $validatedData['email'],
'phone_number' => $validatedData['phone_number'],
'cover_letter' => $validatedData['cover_letter'] ?? null,
]);
return response()->json([
'message' => 'Your application has been submitted successfully!',
]);
}
public function show(Internship $internship)

View File

@@ -3,8 +3,26 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use App\Models\InternshipApplication;
class Internship extends Model
{
//
protected $fillable = [
'title',
'title_description',
'salary_per_month',
'bullets',
'location',
'salary_currency',
];
protected $casts = [
'bullets' => 'array',
];
public function applications(): HasMany
{
return $this->hasMany(InternshipApplication::class);
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class InternshipApplication extends Model
{
protected $fillable = [
'internship_id',
'name',
'birthdate',
'resume_file',
'email',
'phone_number',
'cover_letter',
];
public function internship(): BelongsTo
{
return $this->belongsTo(Internship::class);
}
}