From 8aed6655f82fc5b67afbe771d3ebde639f7f9b8e Mon Sep 17 00:00:00 2001 From: Emil Jamel Mahmuda Date: Fri, 27 Sep 2024 14:49:59 +0700 Subject: [PATCH] feat: add locations feature --- app/Http/Controllers/LocationController.php | 99 ++++++ app/Http/Requests/StoreLocationRequest.php | 40 +++ app/Http/Requests/UpdateLocationRequest.php | 41 +++ app/Models/Location.php | 57 ++++ database/factories/LocationFactory.php | 32 ++ ...24_09_22_084130_create_locations_table.php | 29 ++ database/seeders/DatabaseSeeder.php | 1 + database/seeders/LocationSeeder.php | 18 ++ resources/views/layout/sidebar.blade.php | 2 +- resources/views/locations/create.blade.php | 168 ++++++++++ resources/views/locations/edit.blade.php | 174 ++++++++++ resources/views/locations/index.blade.php | 296 ++++++++++++++++++ resources/views/locations/show.blade.php | 222 +++++++++++++ routes/web.php | 2 + 14 files changed, 1180 insertions(+), 1 deletion(-) create mode 100644 app/Http/Controllers/LocationController.php create mode 100644 app/Http/Requests/StoreLocationRequest.php create mode 100644 app/Http/Requests/UpdateLocationRequest.php create mode 100644 app/Models/Location.php create mode 100644 database/factories/LocationFactory.php create mode 100644 database/migrations/2024_09_22_084130_create_locations_table.php create mode 100644 database/seeders/LocationSeeder.php create mode 100644 resources/views/locations/create.blade.php create mode 100644 resources/views/locations/edit.blade.php create mode 100644 resources/views/locations/index.blade.php create mode 100644 resources/views/locations/show.blade.php diff --git a/app/Http/Controllers/LocationController.php b/app/Http/Controllers/LocationController.php new file mode 100644 index 0000000..d3cf10d --- /dev/null +++ b/app/Http/Controllers/LocationController.php @@ -0,0 +1,99 @@ +query('page'); + $search = $request->query('search'); + + $locations = Location::when($search, function (Builder $query, ?string $search) { + $query->where('name', 'LIKE', "%{$search}%") + ->orWhere('description', 'LIKE', "%{$search}%"); + }) + ->latest() + ->paginate() + ->withQueryString(); + + if ($page > $locations->lastPage() && $page > 1) { + abort(404); + } + + return view('locations.index', compact('locations', 'search')); + } + + /** + * Show the form for creating a new resource. + */ + public function create(): View + { + return view('locations.create'); + } + + /** + * Store a newly created resource in storage. + */ + public function store(StoreLocationRequest $request): RedirectResponse + { + $location = new Location; + $location->name = $request->input('name'); + $location->description = $request->input('description'); + $location->save(); + + return redirect()->route('locations.index') + ->with('message', 'The location has been created.'); + } + + /** + * Display the specified resource. + */ + public function show(Location $location): View + { + return view('locations.show', compact('location')); + } + + /** + * Show the form for editing the specified resource. + */ + public function edit(Location $location): View + { + return view('locations.edit', compact('location')); + } + + /** + * Update the specified resource in storage. + */ + public function update(UpdateLocationRequest $request, Location $location): RedirectResponse + { + $location->name = $request->input('name'); + $location->description = $request->input('description'); + $location->save(); + + return redirect()->route('locations.index') + ->with('message', 'The location has been updated.'); + } + + /** + * Remove the specified resource from storage. + */ + public function destroy(Location $location): RedirectResponse + { + $location->delete(); + + return redirect()->route('locations.index') + ->with('message', 'The location has been deleted.'); + } +} diff --git a/app/Http/Requests/StoreLocationRequest.php b/app/Http/Requests/StoreLocationRequest.php new file mode 100644 index 0000000..424a09e --- /dev/null +++ b/app/Http/Requests/StoreLocationRequest.php @@ -0,0 +1,40 @@ +|string> + */ + public function rules(): array + { + return [ + 'name' => [ + 'required', + 'string', + 'min:3', + 'max:100', + 'unique:locations,name', + ], + 'description' => [ + 'nullable', + 'string', + 'min:3', + 'max:255', + ], + ]; + } +} diff --git a/app/Http/Requests/UpdateLocationRequest.php b/app/Http/Requests/UpdateLocationRequest.php new file mode 100644 index 0000000..e5b9758 --- /dev/null +++ b/app/Http/Requests/UpdateLocationRequest.php @@ -0,0 +1,41 @@ +|string> + */ + public function rules(): array + { + return [ + 'name' => [ + 'required', + 'string', + 'min:3', + 'max:100', + Rule::unique('locations', 'name')->ignore($this->location), + ], + 'description' => [ + 'nullable', + 'string', + 'min:3', + 'max:255', + ], + ]; + } +} diff --git a/app/Models/Location.php b/app/Models/Location.php new file mode 100644 index 0000000..87c993b --- /dev/null +++ b/app/Models/Location.php @@ -0,0 +1,57 @@ + + */ + protected $fillable = [ + 'name', + 'description', + ]; +} diff --git a/database/factories/LocationFactory.php b/database/factories/LocationFactory.php new file mode 100644 index 0000000..57dd911 --- /dev/null +++ b/database/factories/LocationFactory.php @@ -0,0 +1,32 @@ + + */ +class LocationFactory extends Factory +{ + /** + * The name of the factory's corresponding model. + * + * @var class-string<\Illuminate\Database\Eloquent\Model> + */ + protected $model = Location::class; + + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + 'name' => fake()->unique()->word(), + 'description' => fake()->sentence(), + ]; + } +} diff --git a/database/migrations/2024_09_22_084130_create_locations_table.php b/database/migrations/2024_09_22_084130_create_locations_table.php new file mode 100644 index 0000000..24b8b38 --- /dev/null +++ b/database/migrations/2024_09_22_084130_create_locations_table.php @@ -0,0 +1,29 @@ +uuid('id')->primary(); + $table->string('name')->unique(); + $table->text('description')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('locations'); + } +}; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index b51b06c..73ded95 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -17,6 +17,7 @@ public function run(): void BrandSeeder::class, DistributorSeeder::class, ResponsiblePersonSeeder::class, + LocationSeeder::class, ]); } } diff --git a/database/seeders/LocationSeeder.php b/database/seeders/LocationSeeder.php new file mode 100644 index 0000000..f325836 --- /dev/null +++ b/database/seeders/LocationSeeder.php @@ -0,0 +1,18 @@ +count(5) + ->create(); + } +} diff --git a/resources/views/layout/sidebar.blade.php b/resources/views/layout/sidebar.blade.php index d3f793a..a29df26 100644 --- a/resources/views/layout/sidebar.blade.php +++ b/resources/views/layout/sidebar.blade.php @@ -149,7 +149,7 @@
  • - + routeIs('locations.*')) open @endif>
    diff --git a/resources/views/locations/create.blade.php b/resources/views/locations/create.blade.php new file mode 100644 index 0000000..5ed8de7 --- /dev/null +++ b/resources/views/locations/create.blade.php @@ -0,0 +1,168 @@ +@extends('app') + +@section('title', 'Locations') + +@section('content') +
    + + @include('layout.header') + + @include('layout.sidebar') + +
    +
    + + {{-- Breadcrumbs --}} + + {{-- End Breadcrumbs --}} + + {{-- Cards --}} +
    + +
    + @csrf + @method('POST') + +
    +
    + +
    + + {{-- Icon Link --}} + + {{-- End Icon Link --}} + +
    + +
    +
    +
    + {{ __('Create') }} +
    +
    +
    + +
    +
    + +
    +
    +
    + +
    +
    +
    + + {{-- Input --}} +
    + + + +
    + {{-- End Input --}} + +
    + + @error('name') + + {{ $message}} + + @enderror +
    +
    + +
    +
    +
    + + {{-- Input --}} +
    + + + +
    + {{-- End Input --}} + +
    + + @error('description') + + {{ $message }} + + @enderror +
    +
    + +
    +
    +
    + +
    +
    + +
    +
    + + {{-- Button --}} +
    + +
    + {{-- End Button --}} + + {{-- Button --}} +
    + +
    + {{-- End Button --}} + +
    +
    + +
    +
    +
    + +
    + +
    +
    + + @include('layout.footer') + +
    +@endsection diff --git a/resources/views/locations/edit.blade.php b/resources/views/locations/edit.blade.php new file mode 100644 index 0000000..fc6b791 --- /dev/null +++ b/resources/views/locations/edit.blade.php @@ -0,0 +1,174 @@ +@extends('app') + +@section('title', 'Locations') + +@section('content') +
    + + @include('layout.header') + + @include('layout.sidebar') + +
    +
    + + {{-- Breadcrumbs --}} + + {{-- End Breadcrumbs --}} + + {{-- Cards --}} +
    + +
    + @csrf + @method('PUT') + +
    +
    + +
    + + {{-- Icon Link --}} + + {{-- End Icon Link --}} + +
    + +
    +
    +
    + {{ __('Edit') }} +
    +
    +
    + +
    +
    + +
    +
    +
    + +
    +
    +
    + + {{-- Input --}} +
    + + + +
    + {{-- End Input --}} + +
    + + @error('name') + + {{ $message}} + + @enderror +
    +
    + +
    +
    +
    + + {{-- Input --}} +
    + + + +
    + {{-- End Input --}} + +
    + + @error('description') + + {{ $message }} + + @enderror +
    +
    + +
    +
    +
    + +
    +
    + +
    +
    + + {{-- Button --}} +
    + +
    + {{-- End Button --}} + + {{-- Button --}} +
    + +
    + {{-- End Button --}} + +
    +
    + +
    +
    +
    + +
    + +
    +
    + + @include('layout.footer') + +
    +@endsection diff --git a/resources/views/locations/index.blade.php b/resources/views/locations/index.blade.php new file mode 100644 index 0000000..9280e25 --- /dev/null +++ b/resources/views/locations/index.blade.php @@ -0,0 +1,296 @@ +@extends('app') + +@section('title', 'Locations') + +@section('content') +
    + + @include('layout.header') + + @include('layout.sidebar') + +
    +
    + + {{-- Breadcrumbs --}} + + {{-- End Breadcrumbs --}} + + @if (session()->has('message')) + {{-- Toast --}} + + {{-- End Toast --}} + @endif + + {{-- Cards --}} +
    + +
    +
    + +
    +
    +
    + {{ __('All Location') }} +
    +
    +
    + +
    +
    + + {{-- Search --}} +
    + + + +
    + {{-- End Search --}} + +
    +
    + +
    +
    + + {{-- Icon Link --}} + + {{-- End Icon Link --}} + +
    + +
    + + {{-- Dropdown --}} + + {{-- End Dropdown --}} + +
    +
    + +
    +
    + +
    + + {{-- Perfect Scrollbar --}} +
    +
    + + {{-- Table --}} + + + + + + + + + + + + + @forelse($locations as $location) + + + + + + + + @empty + + + + @endforelse + +
    + {{ __('#') }} + + {{ __('Name') }} + + {{ __('Description') }} + + {{ __('Total Assets') }} + + {{ __('Action') }} +
    + {{ $loop->iteration + ($locations->currentPage() - 1) * $locations->perPage() }} + + {{ $location->name }} + + {{ $location->description }} + + {{ $location->assetHistories->count() }} + +
    + @csrf + @method('DELETE') + + {{-- Dropdown --}} +
    + + + +
    + {{-- End Dropdown --}} + +
    +
    + {{ __('No data available.') }} +
    + {{-- End Table --}} + +
    +
    + {{-- End Perfect Scrollbar --}} + +
    + +
    +
    + + {{-- Pagination --}} +
    + {{ $locations->onEachSide(2)->links() }} +
    + {{-- End Pagination --}} + +
    +
    + +
    + {{-- End Cards --}} + +
    +
    + + @include('layout.footer') + +
    +@endsection diff --git a/resources/views/locations/show.blade.php b/resources/views/locations/show.blade.php new file mode 100644 index 0000000..82b9451 --- /dev/null +++ b/resources/views/locations/show.blade.php @@ -0,0 +1,222 @@ +@extends('app') + +@section('title', 'Locations') + +@section('content') +
    + + @include('layout.header') + + @include('layout.sidebar') + +
    +
    + + {{-- Breadcrumbs --}} + + {{-- End Breadcrumbs --}} + + {{-- Cards --}} +
    + +
    +
    + +
    + + {{-- Icon Button --}} + + {{-- End Icon Button --}} + +
    + +
    +
    +
    + {{ __('Details') }} +
    +
    +
    + +
    +
    + @csrf + @method('DELETE') + +
    + + {{-- Icon Link --}} + + {{-- End Icon Link --}} + +
    + +
    + + {{-- Icon Button --}} +
    + +
    + {{-- End Icon Button --}} + +
    + +
    +
    + +
    +
    + +
    +
    + +
      +
    • +
      +
      + + {{ __('Id') }} + +
      + +
      + + {{ $location->id }} + +
      +
      +
    • + +
    • +
      +
      + + {{ __('Name') }} + +
      + +
      + + {{ $location->name }} + +
      +
      +
    • + +
    • +
      +
      + + {{ __('Description') }} + +
      + +
      + + {{ $location->description }} + +
      +
      +
    • + +
    • +
      +
      + + {{ __('Total Assets') }} + +
      + +
      + + {{ $location->assetHistories->count() }} + +
      +
      +
    • + +
    • +
      +
      + + {{ __('Created At') }} + +
      + +
      + + {{ $location->created_at }} + +
      +
      +
    • + +
    • +
      +
      + + {{ __('Updated At') }} + +
      + +
      + + {{ $location->updated_at }} + +
      +
      +
    • +
    + +
    +
    + +
    + {{-- End Cards --}} + +
    +
    + + @include('layout.footer') + +
    +@endsection diff --git a/routes/web.php b/routes/web.php index cb3538d..edf3640 100644 --- a/routes/web.php +++ b/routes/web.php @@ -3,6 +3,7 @@ use App\Http\Controllers\BrandController; use App\Http\Controllers\CategoryController; use App\Http\Controllers\DistributorController; +use App\Http\Controllers\LocationController; use App\Http\Controllers\ResponsiblePersonController; use Illuminate\Support\Facades\Route; @@ -22,3 +23,4 @@ Route::resource('distributors', DistributorController::class); Route::resource('responsible-persons', ResponsiblePersonController::class) ->parameters(['responsible-persons' => 'person']); +Route::resource('locations', LocationController::class);