Compare commits

...

13 commits

22 changed files with 741 additions and 32 deletions

Binary file not shown.

16
app/Models/Employer.php Normal file
View file

@ -0,0 +1,16 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Employer extends Model
{
use HasFactory;
public function jobs()
{
return $this->hasMany(Job::class);
}
}

View file

@ -1 +1,16 @@
<?php
namespace app\Models;
use \Illuminate\Database\Eloquent\Model;
use \Illuminate\Database\Eloquent\Factories\HasFactory;
class Job extends Model {
use HasFactory;
protected $table='job_listings';
protected $fillable=['title','salary','employer_id'];
public function employer()
{
return $this->belongsTo(Employer::class);
}
}

18
app/Models/Rating.php Normal file
View file

@ -0,0 +1,18 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Rating extends Model
{
use HasFactory;
protected $fillable = ['score'];
public function jobs()
{
return $this->belongsToMany(Job::class, relatedPivotKey: 'job_listing_id');
}
}

View file

@ -9,13 +9,12 @@ use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
/** @use HasFactory<\Database\Factories\UserFactory> */
use HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var list<string>
* @var array<int, string>
*/
protected $fillable = [
'name',
@ -26,7 +25,7 @@ class User extends Authenticatable
/**
* The attributes that should be hidden for serialization.
*
* @var list<string>
* @var array<int, string>
*/
protected $hidden = [
'password',

View file

@ -0,0 +1,23 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Employer>
*/
class EmployerFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => fake()->company()
];
}
}

View file

@ -0,0 +1,28 @@
<?php
namespace Database\Factories;
use App\Models\Rating;
use App\Models\Employer;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Job>
*/
class JobFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'title' => fake()->jobTitle(),
'employer_id' => Employer::factory(),
'salary' => fake()->numberBetween($min = 30000, $max = 125000),
'id' => Rating::factory(),
];
}
}

View file

@ -0,0 +1,23 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Tag>
*/
class RatingFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'score' => fake()->randomDigit(),
];
}
}

View file

@ -24,7 +24,8 @@ class UserFactory extends Factory
public function definition(): array
{
return [
'name' => fake()->name(),
'first_name' => fake()->firstName(),
'last_name' => fake()->lastName(),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => static::$password ??= Hash::make('password'),

View file

@ -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::create('job_listings', function (Blueprint $table) {
$table->id();
// $table->unsignedBigInteger('employer_id');
$table->foreignIdFor(\App\Models\Employer::class);
$table->string('title');
$table->string('salary');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('job_listings');
}
};

View file

@ -0,0 +1,28 @@
<?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::create('employers', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('employers');
}
};

View file

@ -0,0 +1,28 @@
<?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::create('ratings', function (Blueprint $table) {
$table->id();
$table->integer('score');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('ratings');
}
};

View file

@ -0,0 +1,35 @@
<?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::create('job_rating', function (Blueprint $table) {
$table->id();
$table->foreignIdFor(\App\Models\Job::class, 'job_listing_id')->constrained()->cascadeOnDelete();
$table->foreignIdFor(\App\Models\Rating::class)->constrained()->cascadeOnDelete();
});
Schema::create('employer_job', function (Blueprint $table) {
$table->id();
$table->foreignIdFor(\App\Models\Job::class, 'job_listing_id')->constrained()->cascadeOnDelete();
$table->foreignIdFor(\App\Models\Employer::class)->constrained()->cascadeOnDelete();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('job_rating');
Schema::dropIfExists('employer_job');
}
};

View file

@ -2,7 +2,9 @@
namespace Database\Seeders;
use App\Models\Job;
use App\Models\User;
use Illuminate\Support\Facades\DB;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
@ -13,12 +15,17 @@ class DatabaseSeeder extends Seeder
*/
public function run(): void
{
// User::factory(10)->create();
User::factory()->create([
'first_name' => 'Test',
'last_name' => 'Test',
'first_name' => 'John',
'last_name' => 'Doe',
'email' => 'test@example.com',
]);
$this->call([
JobSeeder::class,
EmployerJobSeeder::class,
JobRatingSeeder::class,
]);
}
}

View file

@ -0,0 +1,86 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
class EmployerJobSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
DB::table('employer_job')->insert( [
[ "employer_id" => 1, "job_listing_id" => 1],
[ "employer_id" => 10, "job_listing_id" => 2],
[ "employer_id" => 1, "job_listing_id" => 3],
[ "employer_id" => 1, "job_listing_id" => 4],
[ "employer_id" => 6, "job_listing_id" => 4],
[ "employer_id" => 7, "job_listing_id" => 4],
[ "employer_id" => 1, "job_listing_id" => 5],
[ "employer_id" => 1, "job_listing_id" => 6],
[ "employer_id" => 2, "job_listing_id" => 6],
[ "employer_id" => 7, "job_listing_id" => 7],
[ "employer_id" => 9, "job_listing_id" => 7],
[ "employer_id" => 1, "job_listing_id" => 8],
[ "employer_id" => 2, "job_listing_id" => 8],
[ "employer_id" => 1, "job_listing_id" => 9],
[ "employer_id" => 2, "job_listing_id" => 9],
[ "employer_id" => 1, "job_listing_id" => 10],
[ "employer_id" => 2, "job_listing_id" => 10],
[ "employer_id" => 1, "job_listing_id" => 11],
[ "employer_id" => 2, "job_listing_id" => 11],
[ "employer_id" => 1, "job_listing_id" => 12],
[ "employer_id" => 1, "job_listing_id" => 13],
[ "employer_id" => 2, "job_listing_id" => 13],
[ "employer_id" => 1, "job_listing_id" => 14],
[ "employer_id" => 3, "job_listing_id" => 14],
[ "employer_id" => 1, "job_listing_id" => 15],
[ "employer_id" => 2, "job_listing_id" => 15],
[ "employer_id" => 1, "job_listing_id" => 16],
[ "employer_id" => 2, "job_listing_id" => 16],
[ "employer_id" => 7, "job_listing_id" => 17],
[ "employer_id" => 1, "job_listing_id" => 17],
[ "employer_id" => 1, "job_listing_id" => 18],
[ "employer_id" => 2, "job_listing_id" => 18],
[ "employer_id" => 1, "job_listing_id" => 19],
[ "employer_id" => 2, "job_listing_id" => 19],
[ "employer_id" => 1, "job_listing_id" => 20],
[ "employer_id" => 2, "job_listing_id" => 20],
[ "employer_id" => 1, "job_listing_id" => 21],
[ "employer_id" => 3, "job_listing_id" => 21],
[ "employer_id" => 1, "job_listing_id" => 22],
[ "employer_id" => 10, "job_listing_id" => 22],
[ "employer_id" => 1, "job_listing_id" => 23],
[ "employer_id" => 11, "job_listing_id" => 23],
[ "employer_id" => 12, "job_listing_id" => 23],
[ "employer_id" => 1, "job_listing_id" => 24],
[ "employer_id" => 11, "job_listing_id" => 24],
[ "employer_id" => 12, "job_listing_id" => 24],
[ "employer_id" => 1, "job_listing_id" => 25],
[ "employer_id" => 11, "job_listing_id" => 25],
[ "employer_id" => 12, "job_listing_id" => 25],
[ "employer_id" => 1, "job_listing_id" => 26],
[ "employer_id" => 11, "job_listing_id" => 26],
[ "employer_id" => 12, "job_listing_id" => 26],
[ "employer_id" => 5, "job_listing_id" => 27],
[ "employer_id" => 10, "job_listing_id" => 27],
[ "employer_id" => 13, "job_listing_id" => 27],
[ "employer_id" => 5, "job_listing_id" => 28],
[ "employer_id" => 10, "job_listing_id" => 28],
[ "employer_id" => 13, "job_listing_id" => 28],
[ "employer_id" => 8, "job_listing_id" => 29],
[ "employer_id" => 9, "job_listing_id" => 29],
[ "employer_id" => 5, "job_listing_id" => 30],
[ "employer_id" => 10, "job_listing_id" => 30],
[ "employer_id" => 13, "job_listing_id" => 30],
[ "employer_id" => 1, "job_listing_id" => 31],
[ "employer_id" => 1, "job_listing_id" => 32],
[ "employer_id" => 4, "job_listing_id" => 32]
]);
$this->command->info('Seeded the Relationships of Jobs to Employers!');
}
}

View file

@ -0,0 +1,86 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
class JobRatingSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
DB::table('job_rating')->insert( [
[ "rating_id" => 1, "job_listing_id" => 1],
[ "rating_id" => 10, "job_listing_id" => 2],
[ "rating_id" => 1, "job_listing_id" => 3],
[ "rating_id" => 1, "job_listing_id" => 4],
[ "rating_id" => 6, "job_listing_id" => 4],
[ "rating_id" => 7, "job_listing_id" => 4],
[ "rating_id" => 1, "job_listing_id" => 5],
[ "rating_id" => 1, "job_listing_id" => 6],
[ "rating_id" => 2, "job_listing_id" => 6],
[ "rating_id" => 7, "job_listing_id" => 7],
[ "rating_id" => 9, "job_listing_id" => 7],
[ "rating_id" => 1, "job_listing_id" => 8],
[ "rating_id" => 2, "job_listing_id" => 8],
[ "rating_id" => 1, "job_listing_id" => 9],
[ "rating_id" => 2, "job_listing_id" => 9],
[ "rating_id" => 1, "job_listing_id" => 10],
[ "rating_id" => 2, "job_listing_id" => 10],
[ "rating_id" => 1, "job_listing_id" => 11],
[ "rating_id" => 2, "job_listing_id" => 11],
[ "rating_id" => 1, "job_listing_id" => 12],
[ "rating_id" => 1, "job_listing_id" => 13],
[ "rating_id" => 2, "job_listing_id" => 13],
[ "rating_id" => 1, "job_listing_id" => 14],
[ "rating_id" => 3, "job_listing_id" => 14],
[ "rating_id" => 1, "job_listing_id" => 15],
[ "rating_id" => 2, "job_listing_id" => 15],
[ "rating_id" => 1, "job_listing_id" => 16],
[ "rating_id" => 2, "job_listing_id" => 16],
[ "rating_id" => 7, "job_listing_id" => 17],
[ "rating_id" => 1, "job_listing_id" => 17],
[ "rating_id" => 1, "job_listing_id" => 18],
[ "rating_id" => 2, "job_listing_id" => 18],
[ "rating_id" => 1, "job_listing_id" => 19],
[ "rating_id" => 2, "job_listing_id" => 19],
[ "rating_id" => 1, "job_listing_id" => 20],
[ "rating_id" => 2, "job_listing_id" => 20],
[ "rating_id" => 1, "job_listing_id" => 21],
[ "rating_id" => 3, "job_listing_id" => 21],
[ "rating_id" => 1, "job_listing_id" => 22],
[ "rating_id" => 10, "job_listing_id" => 22],
[ "rating_id" => 1, "job_listing_id" => 23],
[ "rating_id" => 11, "job_listing_id" => 23],
[ "rating_id" => 12, "job_listing_id" => 23],
[ "rating_id" => 1, "job_listing_id" => 24],
[ "rating_id" => 11, "job_listing_id" => 24],
[ "rating_id" => 12, "job_listing_id" => 24],
[ "rating_id" => 1, "job_listing_id" => 25],
[ "rating_id" => 11, "job_listing_id" => 25],
[ "rating_id" => 12, "job_listing_id" => 25],
[ "rating_id" => 1, "job_listing_id" => 26],
[ "rating_id" => 11, "job_listing_id" => 26],
[ "rating_id" => 12, "job_listing_id" => 26],
[ "rating_id" => 5, "job_listing_id" => 27],
[ "rating_id" => 10, "job_listing_id" => 27],
[ "rating_id" => 13, "job_listing_id" => 27],
[ "rating_id" => 5, "job_listing_id" => 28],
[ "rating_id" => 10, "job_listing_id" => 28],
[ "rating_id" => 13, "job_listing_id" => 28],
[ "rating_id" => 8, "job_listing_id" => 29],
[ "rating_id" => 9, "job_listing_id" => 29],
[ "rating_id" => 5, "job_listing_id" => 30],
[ "rating_id" => 10, "job_listing_id" => 30],
[ "rating_id" => 13, "job_listing_id" => 30],
[ "rating_id" => 1, "job_listing_id" => 31],
[ "rating_id" => 1, "job_listing_id" => 32],
[ "rating_id" => 4, "job_listing_id" => 32]
]);
$this->command->info('Seeded the Relationships of Ratings to Jobs!');
}
}

View file

@ -0,0 +1,17 @@
<?php
namespace Database\Seeders;
use App\Models\Job;
use Illuminate\Database\Seeder;
class JobSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
Job::factory(33)->create();
}
}

View file

@ -107,6 +107,7 @@
<header class="bg-white shadow-sm">
<div class="mx-auto max-w-7xl px-4 py-6 sm:px-6 lg:px-8">
{{$heading}}
<a href="/jobs/create">Create Job</a>
</div>
</header>
<main>

View file

@ -17,20 +17,14 @@ Create Job
<div class="mt-2">
<div class="flex items-center rounded-md bg-white pl-3 outline-1 -outline-offset-1 outline-gray-300 focus-within:outline-2 focus-within:-outline-offset-2 focus-within:outline-indigo-600">
<div class="shrink-0 text-base text-gray-500 select-none sm:text-sm/6">workcation.com/</div>
<input type="text" name="title" id="title" class="block min-w-0 grow py-1.5 pr-3 pl-1 text-base text-gray-900 placeholder:text-gray-400 focus:outline-none sm:text-sm/6" placeholder="Shift Leader">
<input type="text" name="title" id="title" class="block min-w-0 grow py-1.5 pr-3 pl-1 text-base text-gray-900 placeholder:text-gray-400 focus:outline-none sm:text-sm/6" placeholder="Shift Leader" required>
</div>
@error('title')
<p class="text-xs text-red-500 font-semibold mt-1">{{$message}}</p>
@enderror
</div>
</div>
<div class="sm:col-span-4">
<label for="title" class="block text-sm/6 font-medium text-gray-900">Title</label>
<div class="mt-2">
<div class="flex items-center rounded-md bg-white pl-3 outline-1 -outline-offset-1 outline-gray-300 focus-within:outline-2 focus-within:-outline-offset-2 focus-within:outline-indigo-600">
<div class="shrink-0 text-base text-gray-500 select-none sm:text-sm/6">workcation.com/</div>
<input type="text" name="title" id="title" class="block min-w-0 grow py-1.5 pr-3 pl-1 text-base text-gray-900 placeholder:text-gray-400 focus:outline-none sm:text-sm/6" placeholder="Shift Leader">
</div>
</div>
<div class="sm:col-span-4">
<label for="salary" class="block text-sm/6 font-medium text-gray-900">Title</label>
<div class="mt-2">
@ -38,6 +32,9 @@ Create Job
<div class="shrink-0 text-base text-gray-500 select-none sm:text-sm/6">workcation.com/</div>
<input type="text" name="salary" id="salary" class="block min-w-0 grow py-1.5 pr-3 pl-1 text-base text-gray-900 placeholder:text-gray-400 focus:outline-none sm:text-sm/6" placeholder="$50000">
</div>
@error('salary')
<p class="text-xs text-red-500 font-semibold mt-1">{{$message}}</p>
@enderror
</div>
@ -222,7 +219,7 @@ Create Job
</div>
<div class="mt-6 flex items-center justify-end gap-x-6">
<button type="button" class="text-sm/6 font-semibold text-gray-900">Cancel</button>
<a href="/jobs"><button type="button" class="text-sm/6 font-semibold text-gray-900">Cancel</button></a>
<button type="submit" class="rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-xs hover:bg-indigo-500 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">Save</button>
</div>
</form>

View file

@ -0,0 +1,236 @@
<x-layout>
<x-slot:heading>
Create Job
</x-slot:heading>
<p>
<form method="POST" action="/jobs">
@csrf
<div class="space-y-12">
<div class="border-b border-gray-900/10 pb-12">
<div class="mt-10 grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
<div class="sm:col-span-4">
<label for="title" class="block text-sm/6 font-medium text-gray-900">Title</label>
<div class="mt-2">
<div class="flex items-center rounded-md bg-white pl-3 outline-1 -outline-offset-1 outline-gray-300 focus-within:outline-2 focus-within:-outline-offset-2 focus-within:outline-indigo-600">
<div class="shrink-0 text-base text-gray-500 select-none sm:text-sm/6">workcation.com/</div>
<input type="text" name="title" id="title" class="block min-w-0 grow py-1.5 pr-3 pl-1 text-base text-gray-900 placeholder:text-gray-400 focus:outline-none sm:text-sm/6" placeholder="Shift Leader" required>
</div>
@error('title')
<p class="text-xs text-red-500 font-semibold mt-1">{{$message}}</p>
@enderror
</div>
</div>
<div class="sm:col-span-4">
<label for="salary" class="block text-sm/6 font-medium text-gray-900">Title</label>
<div class="mt-2">
<div class="flex items-center rounded-md bg-white pl-3 outline-1 -outline-offset-1 outline-gray-300 focus-within:outline-2 focus-within:-outline-offset-2 focus-within:outline-indigo-600">
<div class="shrink-0 text-base text-gray-500 select-none sm:text-sm/6">workcation.com/</div>
<input type="text" name="salary" id="salary" class="block min-w-0 grow py-1.5 pr-3 pl-1 text-base text-gray-900 placeholder:text-gray-400 focus:outline-none sm:text-sm/6" placeholder="$50000">
</div>
@error('salary')
<p class="text-xs text-red-500 font-semibold mt-1">{{$message}}</p>
@enderror
</div>
<div class="col-span-full">
<label for="photo" class="block text-sm/6 font-medium text-gray-900">Photo</label>
<div class="mt-2 flex items-center gap-x-3">
<svg class="size-12 text-gray-300" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" data-slot="icon">
<path fill-rule="evenodd" d="M18.685 19.097A9.723 9.723 0 0 0 21.75 12c0-5.385-4.365-9.75-9.75-9.75S2.25 6.615 2.25 12a9.723 9.723 0 0 0 3.065 7.097A9.716 9.716 0 0 0 12 21.75a9.716 9.716 0 0 0 6.685-2.653Zm-12.54-1.285A7.486 7.486 0 0 1 12 15a7.486 7.486 0 0 1 5.855 2.812A8.224 8.224 0 0 1 12 20.25a8.224 8.224 0 0 1-5.855-2.438ZM15.75 9a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z" clip-rule="evenodd" />
</svg>
<button type="button" class="rounded-md bg-white px-2.5 py-1.5 text-sm font-semibold text-gray-900 ring-1 shadow-xs ring-gray-300 ring-inset hover:bg-gray-50">Change</button>
</div>
</div>
<div class="col-span-full">
<label for="cover-photo" class="block text-sm/6 font-medium text-gray-900">Cover photo</label>
<div class="mt-2 flex justify-center rounded-lg border border-dashed border-gray-900/25 px-6 py-10">
<div class="text-center">
<svg class="mx-auto size-12 text-gray-300" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" data-slot="icon">
<path fill-rule="evenodd" d="M1.5 6a2.25 2.25 0 0 1 2.25-2.25h16.5A2.25 2.25 0 0 1 22.5 6v12a2.25 2.25 0 0 1-2.25 2.25H3.75A2.25 2.25 0 0 1 1.5 18V6ZM3 16.06V18c0 .414.336.75.75.75h16.5A.75.75 0 0 0 21 18v-1.94l-2.69-2.689a1.5 1.5 0 0 0-2.12 0l-.88.879.97.97a.75.75 0 1 1-1.06 1.06l-5.16-5.159a1.5 1.5 0 0 0-2.12 0L3 16.061Zm10.125-7.81a1.125 1.125 0 1 1 2.25 0 1.125 1.125 0 0 1-2.25 0Z" clip-rule="evenodd" />
</svg>
<div class="mt-4 flex text-sm/6 text-gray-600">
<label for="file-upload" class="relative cursor-pointer rounded-md bg-white font-semibold text-indigo-600 focus-within:ring-2 focus-within:ring-indigo-600 focus-within:ring-offset-2 focus-within:outline-hidden hover:text-indigo-500">
<span>Upload a file</span>
<input id="file-upload" name="file-upload" type="file" class="sr-only">
</label>
<p class="pl-1">or drag and drop</p>
</div>
<p class="text-xs/5 text-gray-600">PNG, JPG, GIF up to 10MB</p>
</div>
</div>
</div>
</div>
</div>
<div class="border-b border-gray-900/10 pb-12">
<h2 class="text-base/7 font-semibold text-gray-900">Personal Information</h2>
<p class="mt-1 text-sm/6 text-gray-600">Use a permanent address where you can receive mail.</p>
<div class="mt-10 grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
<div class="sm:col-span-3">
<label for="first-name" class="block text-sm/6 font-medium text-gray-900">First name</label>
<div class="mt-2">
<input type="text" name="first-name" id="first-name" autocomplete="given-name" class="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6">
</div>
</div>
<div class="sm:col-span-3">
<label for="last-name" class="block text-sm/6 font-medium text-gray-900">Last name</label>
<div class="mt-2">
<input type="text" name="last-name" id="last-name" autocomplete="family-name" class="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6">
</div>
</div>
<div class="sm:col-span-4">
<label for="email" class="block text-sm/6 font-medium text-gray-900">Email address</label>
<div class="mt-2">
<input id="email" name="email" type="email" autocomplete="email" class="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6">
</div>
</div>
<div class="sm:col-span-3">
<label for="country" class="block text-sm/6 font-medium text-gray-900">Country</label>
<div class="mt-2 grid grid-cols-1">
<select id="country" name="country" autocomplete="country-name" class="col-start-1 row-start-1 w-full appearance-none rounded-md bg-white py-1.5 pr-8 pl-3 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6">
<option>United States</option>
<option>Canada</option>
<option>Mexico</option>
</select>
<svg class="pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-gray-500 sm:size-4" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" data-slot="icon">
<path fill-rule="evenodd" d="M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" />
</svg>
</div>
</div>
<div class="col-span-full">
<label for="street-address" class="block text-sm/6 font-medium text-gray-900">Street address</label>
<div class="mt-2">
<input type="text" name="street-address" id="street-address" autocomplete="street-address" class="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6">
</div>
</div>
<div class="sm:col-span-2 sm:col-start-1">
<label for="city" class="block text-sm/6 font-medium text-gray-900">City</label>
<div class="mt-2">
<input type="text" name="city" id="city" autocomplete="address-level2" class="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6">
</div>
</div>
<div class="sm:col-span-2">
<label for="region" class="block text-sm/6 font-medium text-gray-900">State / Province</label>
<div class="mt-2">
<input type="text" name="region" id="region" autocomplete="address-level1" class="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6">
</div>
</div>
<div class="sm:col-span-2">
<label for="postal-code" class="block text-sm/6 font-medium text-gray-900">ZIP / Postal code</label>
<div class="mt-2">
<input type="text" name="postal-code" id="postal-code" autocomplete="postal-code" class="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6">
</div>
</div>
</div>
</div>
<div class="border-b border-gray-900/10 pb-12">
<h2 class="text-base/7 font-semibold text-gray-900">Notifications</h2>
<p class="mt-1 text-sm/6 text-gray-600">We'll always let you know about important changes, but you pick what else you want to hear about.</p>
<div class="mt-10 space-y-10">
<fieldset>
<legend class="text-sm/6 font-semibold text-gray-900">By email</legend>
<div class="mt-6 space-y-6">
<div class="flex gap-3">
<div class="flex h-6 shrink-0 items-center">
<div class="group grid size-4 grid-cols-1">
<input id="comments" aria-describedby="comments-description" name="comments" type="checkbox" checked class="col-start-1 row-start-1 appearance-none rounded-sm border border-gray-300 bg-white checked:border-indigo-600 checked:bg-indigo-600 indeterminate:border-indigo-600 indeterminate:bg-indigo-600 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 disabled:border-gray-300 disabled:bg-gray-100 disabled:checked:bg-gray-100 forced-colors:appearance-auto">
<svg class="pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-disabled:stroke-gray-950/25" viewBox="0 0 14 14" fill="none">
<path class="opacity-0 group-has-checked:opacity-100" d="M3 8L6 11L11 3.5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
<path class="opacity-0 group-has-indeterminate:opacity-100" d="M3 7H11" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</div>
</div>
<div class="text-sm/6">
<label for="comments" class="font-medium text-gray-900">Comments</label>
<p id="comments-description" class="text-gray-500">Get notified when someones posts a comment on a posting.</p>
</div>
</div>
<div class="flex gap-3">
<div class="flex h-6 shrink-0 items-center">
<div class="group grid size-4 grid-cols-1">
<input id="candidates" aria-describedby="candidates-description" name="candidates" type="checkbox" class="col-start-1 row-start-1 appearance-none rounded-sm border border-gray-300 bg-white checked:border-indigo-600 checked:bg-indigo-600 indeterminate:border-indigo-600 indeterminate:bg-indigo-600 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 disabled:border-gray-300 disabled:bg-gray-100 disabled:checked:bg-gray-100 forced-colors:appearance-auto">
<svg class="pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-disabled:stroke-gray-950/25" viewBox="0 0 14 14" fill="none">
<path class="opacity-0 group-has-checked:opacity-100" d="M3 8L6 11L11 3.5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
<path class="opacity-0 group-has-indeterminate:opacity-100" d="M3 7H11" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</div>
</div>
<div class="text-sm/6">
<label for="candidates" class="font-medium text-gray-900">Candidates</label>
<p id="candidates-description" class="text-gray-500">Get notified when a candidate applies for a job.</p>
</div>
</div>
<div class="flex gap-3">
<div class="flex h-6 shrink-0 items-center">
<div class="group grid size-4 grid-cols-1">
<input id="offers" aria-describedby="offers-description" name="offers" type="checkbox" class="col-start-1 row-start-1 appearance-none rounded-sm border border-gray-300 bg-white checked:border-indigo-600 checked:bg-indigo-600 indeterminate:border-indigo-600 indeterminate:bg-indigo-600 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 disabled:border-gray-300 disabled:bg-gray-100 disabled:checked:bg-gray-100 forced-colors:appearance-auto">
<svg class="pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-disabled:stroke-gray-950/25" viewBox="0 0 14 14" fill="none">
<path class="opacity-0 group-has-checked:opacity-100" d="M3 8L6 11L11 3.5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
<path class="opacity-0 group-has-indeterminate:opacity-100" d="M3 7H11" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</div>
</div>
<div class="text-sm/6">
<label for="offers" class="font-medium text-gray-900">Offers</label>
<p id="offers-description" class="text-gray-500">Get notified when a candidate accepts or rejects an offer.</p>
</div>
</div>
</div>
</fieldset>
<fieldset>
<legend class="text-sm/6 font-semibold text-gray-900">Push notifications</legend>
<p class="mt-1 text-sm/6 text-gray-600">These are delivered via SMS to your mobile phone.</p>
<div class="mt-6 space-y-6">
<div class="flex items-center gap-x-3">
<input id="push-everything" name="push-notifications" type="radio" checked class="relative size-4 appearance-none rounded-full border border-gray-300 bg-white before:absolute before:inset-1 before:rounded-full before:bg-white not-checked:before:hidden checked:border-indigo-600 checked:bg-indigo-600 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 disabled:border-gray-300 disabled:bg-gray-100 disabled:before:bg-gray-400 forced-colors:appearance-auto forced-colors:before:hidden">
<label for="push-everything" class="block text-sm/6 font-medium text-gray-900">Everything</label>
</div>
<div class="flex items-center gap-x-3">
<input id="push-email" name="push-notifications" type="radio" class="relative size-4 appearance-none rounded-full border border-gray-300 bg-white before:absolute before:inset-1 before:rounded-full before:bg-white not-checked:before:hidden checked:border-indigo-600 checked:bg-indigo-600 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 disabled:border-gray-300 disabled:bg-gray-100 disabled:before:bg-gray-400 forced-colors:appearance-auto forced-colors:before:hidden">
<label for="push-email" class="block text-sm/6 font-medium text-gray-900">Same as email</label>
</div>
<div class="flex items-center gap-x-3">
<input id="push-nothing" name="push-notifications" type="radio" class="relative size-4 appearance-none rounded-full border border-gray-300 bg-white before:absolute before:inset-1 before:rounded-full before:bg-white not-checked:before:hidden checked:border-indigo-600 checked:bg-indigo-600 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 disabled:border-gray-300 disabled:bg-gray-100 disabled:before:bg-gray-400 forced-colors:appearance-auto forced-colors:before:hidden">
<label for="push-nothing" class="block text-sm/6 font-medium text-gray-900">No push notifications</label>
</div>
</div>
</fieldset>
</div>
</div>
</div>
<div class="mt-6 flex items-center justify-between gap-x-6">
    <div class="flex items-center">
        <button form="delete-form" class="text-red-500 text-sm font-bold">Delete</button>
    </div>
    <div class="flex items-center gap-x-6">
        <a href="\jobs\{{$job->id}}" class="text-sm font-semibold leading-6 text-gray-900">Cancel</a>
        <div>
            <button type="submit" class="rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">Update</button>
                    </div>
    </div>
  </div>
</form>
<form method='POST' action="/jobs/{{$job->id}}" id="delete-form" class="hidden">
    @csrf
    @method('DELETE')
</form>
</p>
</x-layout>

View file

@ -2,8 +2,11 @@
<x-slot:heading>
Job
</x-slot:heading>
<h2 class="font-bold txt-lg">{{$job['title']}}</h2>
<h2 class="font-bold txt-lg">{{ $job['title'] ?? 'No title available' }}</h2>
<p>
This job pays {{$job['salary']}} per year
This job pays {{ $job['salary'] ?? 'N/A' }} per year
</p>
<p>
<a href="/jobs/{{$job->id}}/edit">Edit</a>
</a>
</x-layout>

View file

@ -8,35 +8,65 @@ Route::get('/', function () {
});
Route::get('/jobs', function () {
$jobs = Job::orderBy('salary','desc')->paginate(5);
$jobs = Job::orderBy('salary','desc')->latest()->paginate(5);
return view('jobs/index', [
'jobs' => $jobs
]);
});
Route::get('/jobs/{id}/edit', function ($id) {
$job=Job::find($id);
return view('jobs.edit',['job'=>$job]);
});
// return view('jobs', ['jobs' => $jobs]);
// });
//Update
Route::patch('/jobs/{id}', function ($id) {
//validate
request()->validate([
'title'=>['required','min:3'],
'salary'=>['required']
]);
$job=Job::findOrFail($id);
$job->update([
'title'=>request('title'),
'salary'=>request('salary')
]);
return redirect('/jobs/'. $job->id);
});
//Destroy
Route::delete('/jobs/{id}', function ($id) {
$job=Job::findOrFail($id);
$job->delete();
return redirect('/jobs');
});
Route::get('/contact', function () {
return view('contact');
});
Route::get('/jobs/create', function () {
return view('jobs/create');
});
Route::get('/jobs/{id}', function ($id) {
$job = Job::find($id);
return view('jobs/show', ['job' => $job]);
});
Route::get('/jobs/ceate', function () {
return view('jobs/create');
});
Route::post('/jobs', function () {
    Job::create([
        'title'=>request('title'),
        'salary'=>request('salary'),
        'employer_id'=>1
    ]);
    return redirect('/jobs');
request()->validate([
'title'=>['required','min:3'],
'salary'=>['required']
]);
Job::create(['title'=>request('title'),'salary'=>request('salary'),'employer_id'=>1]);
return redirect('/jobs');
});
@ -61,5 +91,6 @@ Route::post('/jobs', function () {