From cf7cc142a7c8b27545b12ea904b4832bfc63059c Mon Sep 17 00:00:00 2001 From: Miguel Nogueira Date: Fri, 8 May 2020 08:10:25 +0100 Subject: [PATCH] Add Dynamic Form Processing for Custom Forms --- app/Application.php | 8 ++- .../Controllers/ApplicationController.php | 67 +++++++++++++++++++ app/Http/Controllers/HomeController.php | 3 + app/Response.php | 6 +- ...08_063141_add_vacancy_i_d_to_responses.php | 32 +++++++++ .../application-rendering/apply.blade.php | 56 +++++++++++----- .../dashboard/user/applications.blade.php | 18 +++++ routes/web.php | 3 + 8 files changed, 174 insertions(+), 19 deletions(-) create mode 100644 database/migrations/2020_05_08_063141_add_vacancy_i_d_to_responses.php diff --git a/app/Application.php b/app/Application.php index c0b8274..319296a 100644 --- a/app/Application.php +++ b/app/Application.php @@ -6,5 +6,11 @@ use Illuminate\Database\Eloquent\Model; class Application extends Model { - // + public $fillable = [ + + 'applicantUserID', + 'applicantFormResponseID', + 'applicantStatus' + + ]; } diff --git a/app/Http/Controllers/ApplicationController.php b/app/Http/Controllers/ApplicationController.php index aecf4a9..0d2cb5f 100644 --- a/app/Http/Controllers/ApplicationController.php +++ b/app/Http/Controllers/ApplicationController.php @@ -2,8 +2,13 @@ namespace App\Http\Controllers; +use App\Application; +use Illuminate\Support\Facades\Log; +use App\Response; use App\Vacancy; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Validator; class ApplicationController extends Controller { @@ -59,4 +64,66 @@ class ApplicationController extends Controller } } + + public function saveApplicationAnswers(Request $request, $vacancySlug) + { + $vacancy = Vacancy::with('forms')->where('vacancySlug', $vacancySlug)->get(); + + Log::info('Processing new application!'); + + $formStructure = json_decode($vacancy->first()->forms->formStructure, true); + $responseStructure = []; + + $excludedNames = [ + '_token', + ]; + + $validator = []; + + foreach($request->all() as $fieldName => $value) + { + if(!in_array($fieldName, $excludedNames)) + { + $validator[$fieldName] = 'required|string'; + + $responseStructure['responses'][$fieldName]['type'] = $formStructure['fields'][$fieldName]['type'] ?? 'Unavailable'; + $responseStructure['responses'][$fieldName]['title'] = $formStructure['fields'][$fieldName]['title']; + $responseStructure['responses'][$fieldName]['response'] = $value; + } + } + + Log::info('Built response & validator structure!'); + + $validation = Validator::make($request->all(), $validator); + + if (!$validation->fails()) + { + $response = Response::create([ + 'responseFormID' => $vacancy->first()->forms->id, + 'associatedVacancyID' => $vacancy->first()->id, // Since a form can be used by multiple vacancies, we can only know which specific vacancy this response ties to by using a vacancy ID + 'responseData' => json_encode($responseStructure) + ]); + + Log::info('Registered form response for user ' . Auth::user()->name . ' for vacancy ' . $vacancy->first()->vacancyName); + + Application::create([ + 'applicantUserID' => Auth::user()->id, + 'applicantFormResponseID' => $response->id, + 'applicationStatus' => 'STAGE_SUBMITTED', + ]); + + Log::info('Submitted application for user ' . Auth::user()->name . ' with response ID' . $response->id); + + $request->session()->flash('success', 'Thank you for your application! It will be reviewed as soon as possible.'); + return redirect()->to(route('userPendingApps')); + } + else + { + Log::warning('Application form for ' . Auth::user()->name . ' contained errors, resetting!'); + $request->session()->flash('error', 'There are one or more errors in your application. Please make sure none of your fields are empty, since they are all required.'); + + } + + return redirect()->back(); + } } diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index e1c4ba2..d92e45a 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -14,6 +14,9 @@ class HomeController extends Controller */ public function index() { + // TODO: Relationships for Applications, Users and Responses + // Also prevent apps if user already has one in the space of 30d + // Display apps in the relevant menus return view('home') ->with('positions', Vacancy::where('vacancyStatus', 'OPEN')->get()); } diff --git a/app/Response.php b/app/Response.php index 7609f8e..4cdc3e4 100644 --- a/app/Response.php +++ b/app/Response.php @@ -6,5 +6,9 @@ use Illuminate\Database\Eloquent\Model; class Response extends Model { - // + public $fillable = [ + 'responseFormID', + 'associatedVacancyID', + 'responseData' + ]; } diff --git a/database/migrations/2020_05_08_063141_add_vacancy_i_d_to_responses.php b/database/migrations/2020_05_08_063141_add_vacancy_i_d_to_responses.php new file mode 100644 index 0000000..e8b8591 --- /dev/null +++ b/database/migrations/2020_05_08_063141_add_vacancy_i_d_to_responses.php @@ -0,0 +1,32 @@ +bigInteger('associatedVacancyID')->unsigned()->after('responseFormID'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('responses', function (Blueprint $table) { + $table->dropColumn('associatedVacancyID'); + }); + } +} diff --git a/resources/views/dashboard/application-rendering/apply.blade.php b/resources/views/dashboard/application-rendering/apply.blade.php index 8001dee..cf15541 100644 --- a/resources/views/dashboard/application-rendering/apply.blade.php +++ b/resources/views/dashboard/application-rendering/apply.blade.php @@ -6,6 +6,24 @@

My Account / Apply / {{$vacancy->vacancyName}} Application

@stop +@section('js') + + @if (session()->has('success')) + + + + @elseif(session()->has('error')) + + + + @endif + +@stop + @section('content') @@ -65,38 +83,42 @@
- @foreach($preprocessedForm['fields'] as $fieldName => $field) +
+ @csrf + @foreach($preprocessedForm['fields'] as $fieldName => $field) - @switch ($field['type']) + @switch ($field['type']) - @case('textarea') + @case('textarea') -
+
- - -
+
- @break + @break - @case('textbox') + @case('textbox') -
+
- - + + -
+
- @break + @break - @endswitch + @endswitch - @endforeach + @endforeach + +
diff --git a/resources/views/dashboard/user/applications.blade.php b/resources/views/dashboard/user/applications.blade.php index 48fe7ca..523974c 100644 --- a/resources/views/dashboard/user/applications.blade.php +++ b/resources/views/dashboard/user/applications.blade.php @@ -8,6 +8,24 @@ @stop +@section('js') + + @if (session()->has('success')) + + + + @elseif(session()->has('error')) + + + + @endif + +@stop + @section('content')
diff --git a/routes/web.php b/routes/web.php index 66c0e61..d1bd779 100644 --- a/routes/web.php +++ b/routes/web.php @@ -50,6 +50,9 @@ Route::group(['middleware' => 'auth'], function(){ Route::get('positions/{vacancySlug}', 'ApplicationController@renderApplicationForm') ->name('renderApplicationForm'); + Route::post('positions/{vacancySlug}/submit', 'ApplicationController@saveApplicationAnswers') + ->name('saveApplicationForm'); + }); Route::group(['prefix' => '/profile'], function (){