Minimal Viable Product + Refactor to pinia store + Fix PDF export
This commit is contained in:
50
app/Http/Controllers/ResumeComponentController.php
Normal file
50
app/Http/Controllers/ResumeComponentController.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\StoreResumeComponentRequest;
|
||||
use App\Http\Requests\UpdateResumeComponentRequest;
|
||||
use App\Models\ResumeComponent;
|
||||
|
||||
class ResumeComponentController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return ResumeComponent::all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(StoreResumeComponentRequest $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(ResumeComponent $resumeComponent)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(UpdateResumeComponentRequest $request, ResumeComponent $resumeComponent)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(ResumeComponent $resumeComponent)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,9 @@ namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\StoreResumeComponentPlacementRequest;
|
||||
use App\Http\Requests\UpdateResumeComponentPlacementRequest;
|
||||
use App\Models\Resume;
|
||||
use App\Models\ResumeComponent;
|
||||
use App\Models\ResumeComponentData;
|
||||
use App\Models\ResumeComponentPlacement;
|
||||
use Log;
|
||||
|
||||
@@ -24,9 +27,29 @@ class ResumeComponentPlacementController extends Controller
|
||||
*/
|
||||
public function store(StoreResumeComponentPlacementRequest $request)
|
||||
{
|
||||
dd('hello');
|
||||
// === VERIFICATIONS ===
|
||||
$user = $request->user();
|
||||
$validated = $request->validated();
|
||||
// 1) User owns the linked resume
|
||||
$resume = Resume::find($validated['resume_id']);
|
||||
if (!$resume || !$user->can('update', $resume)) {
|
||||
return response()->json(['error' => 'You do not own that resume'], 403);
|
||||
}
|
||||
// 2) the resume does not already have a component placement with that order
|
||||
$existingPlacement = ResumeComponentPlacement::where('resume_id', $resume->id)
|
||||
->where('order', $validated['order'])
|
||||
->first();
|
||||
if ($existingPlacement) {
|
||||
return response()->json(['error' => 'Component placement with that order already exists'], 422);
|
||||
}
|
||||
|
||||
//
|
||||
// === CREATION ===
|
||||
$newResumeComponentData = ResumeComponentData::createWithInputs(ResumeComponent::find($validated['component_id']));
|
||||
$componentPlacement = $resume->componentsPlacements()->create([
|
||||
'resume_component_data_id' => $newResumeComponentData->id,
|
||||
'order' => $validated['order'],
|
||||
]);
|
||||
return response()->json($componentPlacement->load('componentData.component', 'componentData.inputData.componentInput.dataType'), 201);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,7 +79,6 @@ class ResumeComponentPlacementController extends Controller
|
||||
// Update component data
|
||||
$componentData = collect($data['component_data'])->except(['input_data', 'component'])->toArray();
|
||||
$componentData['resume_component_id'] = $data['component_data']['component']['id'] ?? null;
|
||||
$componentData['resume_component_placement_id'] = $resumeComponentPlacement->id;
|
||||
$resumeComponentPlacement->componentData()->update($componentData);
|
||||
|
||||
// Update input data
|
||||
@@ -79,13 +101,27 @@ class ResumeComponentPlacementController extends Controller
|
||||
return response()->json($resumeComponentPlacement);
|
||||
}
|
||||
|
||||
public function unlink(ResumeComponentPlacement $placement)
|
||||
{
|
||||
// Load relations
|
||||
$placement->load('componentData.component', 'componentData.inputData');
|
||||
|
||||
// Create a new ResumeComponentData without inputs
|
||||
$newComponentData = ResumeComponentData::copyFrom($placement->componentData()->first());
|
||||
|
||||
// Update the placement to link to the new component data
|
||||
$placement->resume_component_data_id = $newComponentData->id;
|
||||
$placement->save();
|
||||
|
||||
return response()->json($newComponentData->load('component', 'inputData.componentInput.dataType'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(ResumeComponentPlacement $resumeComponentPlacement)
|
||||
{
|
||||
dd('hello');
|
||||
|
||||
//
|
||||
$resumeComponentPlacement->delete();
|
||||
return response()->json(null, 204);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ use App\Models\Resume;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Inertia\Inertia;
|
||||
use Illuminate\Http\Request;
|
||||
use \Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
|
||||
class ResumeController extends Controller
|
||||
{
|
||||
@@ -31,11 +32,27 @@ class ResumeController extends Controller
|
||||
}
|
||||
|
||||
$newResume = new Resume();
|
||||
$newResume->creator()->associate($request->user());
|
||||
$newResume->save();
|
||||
// Redirect to the edit page for the new resume
|
||||
return redirect()->route('resumes.edit', $newResume);
|
||||
}
|
||||
|
||||
public function duplicate(Resume $resume)
|
||||
{
|
||||
$newResume = $resume->replicate();
|
||||
$newResume->name = $resume->name . ' (Copy)';
|
||||
$newResume->save();
|
||||
|
||||
foreach ($resume->componentsPlacements as $placement) {
|
||||
$newPlacement = $placement->replicate();
|
||||
$newPlacement->resume_id = $newResume->id;
|
||||
$newPlacement->save();
|
||||
}
|
||||
|
||||
return redirect()->route('resumes.edit', $newResume);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
@@ -55,8 +72,15 @@ class ResumeController extends Controller
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit(Request $request, Resume $resume)
|
||||
public function edit(Request $request, int $resumeId)
|
||||
{
|
||||
$resume = null;
|
||||
try {
|
||||
$resume = Resume::findOrFail($resumeId);
|
||||
} catch (ModelNotFoundException $e) {
|
||||
return redirect()->route(config('app.redirect_route'));
|
||||
}
|
||||
|
||||
// Check if the user can edit the resume
|
||||
if ($request->user()->cannot('update', $resume)) {
|
||||
abort(403);
|
||||
@@ -80,6 +104,7 @@ class ResumeController extends Controller
|
||||
*/
|
||||
public function destroy(Resume $resume)
|
||||
{
|
||||
//
|
||||
$resume->delete();
|
||||
return response()->json(null, 204);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Models\ResumeComponentPlacement;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreResumeComponentPlacementRequest extends FormRequest
|
||||
@@ -11,7 +12,7 @@ class StoreResumeComponentPlacementRequest extends FormRequest
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return false;
|
||||
return $this->user()->can('create', ResumeComponentPlacement::class);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -22,7 +23,9 @@ class StoreResumeComponentPlacementRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
'component_id' => ['required', 'exists:resume_components,id'],
|
||||
'resume_id' => ['required', 'exists:resumes,id'],
|
||||
'order' => ['required', 'integer'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,4 +36,9 @@ class ResumeComponent extends Model
|
||||
return $this->belongsToMany(ResumeComponentPlacement::class)
|
||||
->using(ResumeComponentData::class);
|
||||
}
|
||||
|
||||
public function inputs(): HasMany
|
||||
{
|
||||
return $this->hasMany(ResumeComponentInput::class, 'resume_component_id');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,24 +2,64 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\Pivot;
|
||||
|
||||
class ResumeComponentData extends Pivot
|
||||
class ResumeComponentData extends Model
|
||||
{
|
||||
protected $table = 'resume_component_data';
|
||||
|
||||
public function component()
|
||||
protected $fillable = [
|
||||
'resume_component_id',
|
||||
];
|
||||
|
||||
public function component(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ResumeComponent::class, 'resume_component_id');
|
||||
}
|
||||
|
||||
public function componentPlacements()
|
||||
public function componentPlacements(): HasMany
|
||||
{
|
||||
return $this->hasMany(ResumeComponentPlacement::class);
|
||||
}
|
||||
|
||||
public function inputData()
|
||||
public function inputData(): HasMany
|
||||
{
|
||||
return $this->hasMany(ResumeComponentInputData::class, 'resume_component_data_id');
|
||||
}
|
||||
|
||||
public static function createWithInputs(ResumeComponent $component): ResumeComponentData
|
||||
{
|
||||
$componentData = ResumeComponentData::create([
|
||||
'resume_component_id' => $component->id,
|
||||
]);
|
||||
|
||||
foreach ($component->inputs()->get() as $input) {
|
||||
$componentData->inputData()->create([
|
||||
'resume_component_data_id' => $componentData->id,
|
||||
'resume_component_input_id' => $input->id,
|
||||
]);
|
||||
}
|
||||
|
||||
return $componentData->refresh();
|
||||
}
|
||||
|
||||
public static function copyFrom(ResumeComponentData $existingData): ResumeComponentData
|
||||
{
|
||||
$componentData = ResumeComponentData::create([
|
||||
'resume_component_id' => $existingData->resume_component_id,
|
||||
]);
|
||||
|
||||
foreach ($existingData->inputData()->get() as $inputDatum) {
|
||||
$componentData->inputData()->create([
|
||||
'resume_component_data_id' => $componentData->id,
|
||||
'resume_component_input_id' => $inputDatum->resume_component_input_id,
|
||||
'value' => $inputDatum->value,
|
||||
]);
|
||||
}
|
||||
|
||||
return $componentData->refresh();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,11 +24,6 @@ class ResumeComponentInput extends Pivot
|
||||
'placeholder'
|
||||
];
|
||||
|
||||
public function resumes()
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
public function component(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ResumeComponent::class);
|
||||
|
||||
@@ -8,6 +8,12 @@ class ResumeComponentInputData extends Pivot
|
||||
{
|
||||
protected $table = 'resume_component_input_data';
|
||||
|
||||
protected $fillable = [
|
||||
'resume_component_data_id',
|
||||
'resume_component_input_id',
|
||||
'value',
|
||||
];
|
||||
|
||||
|
||||
public function componentData()
|
||||
{
|
||||
|
||||
@@ -4,14 +4,21 @@ namespace App\Models;
|
||||
|
||||
use App\Policies\ResumeComponentPlacementPolicy;
|
||||
use Illuminate\Database\Eloquent\Attributes\UsePolicy;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\Pivot;
|
||||
|
||||
#[UsePolicy(ResumeComponentPlacementPolicy::class)]
|
||||
class ResumeComponentPlacement extends Pivot
|
||||
class ResumeComponentPlacement extends Model
|
||||
{
|
||||
protected $table = 'resume_component_placements';
|
||||
|
||||
protected $fillable = [
|
||||
'resume_component_data_id',
|
||||
'resume_id',
|
||||
'order',
|
||||
];
|
||||
|
||||
public function componentData(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ResumeComponentData::class, 'resume_component_data_id');
|
||||
|
||||
@@ -32,6 +32,11 @@ class ResumeComponentPlacementPolicy
|
||||
return true;
|
||||
}
|
||||
|
||||
public function createForResume(User $user, ResumeComponentPlacement $componentPlacement): bool
|
||||
{
|
||||
return $user->can('update', $componentPlacement->load('resume')->resume);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user