feat: Implement home page API endpoint

- Add HomeController with index method to provide home page data
- Fetch and include menu with items, limiting selected fields for optimization
- Fetch and include latest 6 sliders using SliderResource
- Fetch and include top 8 parent categories with their products using CategoryResource
- Fetch and include active advertisements with available clicks using AdvResource
- Fetch and include latest 8 posts using PostResource
- Return all collected data as a successful JSON response
pull/45/head
cyberali 2 months ago
parent 3f75d919cf
commit f794d1f083

@ -0,0 +1,38 @@
<?php
namespace App\Http\Controllers\Api\Web;
use App\Http\Controllers\Controller;
use App\Http\Resources\AdvResource;
use App\Http\Resources\CategoryResource;
use App\Http\Resources\PostResource;
use App\Http\Resources\ProductResource;
use App\Http\Resources\SliderResource;
use App\Models\Adv;
use App\Models\Category;
use App\Models\Menu;
use App\Models\Post;
use App\Models\Product;
use App\Models\Slider;
use Illuminate\Http\Request;
class HomeController extends Controller
{
public function index()
{
$data = [];
$data['menu'] = Menu::with(['items' => function ($query) {
$query->select(['id', 'title', 'menuable_id', 'menuable_type', 'kind', 'meta', 'parent', 'sort', 'user_id', 'menu_id']);
}])->first(['id', 'name']);
$data['slider'] = SliderResource::collection(Slider::take(6)->get());
$data['categories'] = CategoryResource::collection(Category::with('products')->whereNull('parent_id')->orderBy('sort')->take(8)->get());
$data['adv'] = AdvResource::collection(
Adv::query()
->where('status', true)
->whereColumn('click', '<', 'max_click')
->get()
);
$data['post'] = PostResource::collection(Post::orderByDesc('created_at')->take(8)->get());
return success($data);
}
}

@ -0,0 +1,28 @@
<?php
namespace App\Http\Resources;
use App\Models\Adv;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class AdvResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
/**
* @var $this Adv
*/
return [
'id' => $this->id,
'image' => $this->imgUrl,
'title' => $this->title,
'link' => $this->link,
];
}
}

@ -0,0 +1,39 @@
<?php
namespace App\Http\Resources;
use App\Models\Category;
use App\Models\Product;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
//use Illuminate\Http\Resources\Json\ResourceCollection;
class CategoryResource extends JsonResource
{
/**
* Transform the resource collection into an array.
*
* @return array<int|string, mixed>
*/
public function toArray(Request $request, $data = null): array
{
/**
* @var $this Category
*/
$request->merge([
'loadCategory' => false
]);
return [
'id' => $this->id,
'name' => $this->name,
'slug' => $this->slug,
'subtitle' => $this->subtitle,
'description' => $this->description,
'sort' => $this->sort,
'image' => $this->image,
'bg' => $this->bg,
'products' => $this->when($request->input('loadProduct' , true) , ProductResource::collection($this->products)->additional(['request' => $request['loadCategory']]) )
];
}
}

@ -0,0 +1,38 @@
<?php
namespace App\Http\Resources;
use App\Models\Post;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class PostResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
/**
* @var $this Post
*/
return [
'id' => $this->id,
'slug' => $this->slug,
'subtitle' => $this->subtitle,
'body' => $this->body,
'group' => $this->load('groups'),
'author' => $this->load('author'),
'view' => $this->view,
'is_pinned' => $this->is_pinned,
'hash' => $this->hash,
'like' => $this->like,
'dislike' => $this->dislike,
'icon' => $this->icon,
'created_at' => $this->created_at,
];
}
}

@ -0,0 +1,39 @@
<?php
namespace App\Http\Resources;
use App\Models\Product;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class ProductResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
/**
* @var $this Product
*/
$request->merge([
'loadProduct' => false
]);
return [
'id' => $this->id,
'slug' => $this->slug,
'description' => $this->description,
'table' => $this->table,
'sku' => $this->sku,
'virtual' => $this->virtual,
'downloadable' => $this->downloadable,
'price' => $this->price,
'buy_price' => $this->buy_price,
'average_rating' => $this->average_rating,
'view' => $this->view,
'category' => $this->when($request->input('loadCategory', true), new CategoryResource($this->category))
];
}
}

@ -0,0 +1,32 @@
<?php
namespace App\Http\Resources;
use App\Models\Slider;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class SliderResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
/**
* @var $this Slider
*/
return [
'id' => $this->id,
'body' => $this->body,
'image' => $this->imgUrl(),
'tag' => $this->tag,
'user_id' => $this->user_id,
'status' => $this->status,
'data' => $this->data,
'user' => $this->load('author')
];
}
}

@ -83,7 +83,7 @@ class Category extends Model
public function products() public function products()
{ {
return $this->belongsToMany(Product::class); return $this->hasMany(Product::class);
} }

@ -9,12 +9,12 @@ Route::get('/user', function (Request $request) {
Route::get('', function () { Route::get('', function () {
return 'xshop api:'.config('app.name'); return 'xshop api:' . config('app.name');
}); });
Route::get('/clear', function () { Route::get('/clear', function () {
if (!auth()->check()){ if (!auth()->check()) {
return abort(403); return abort(403);
} }
Artisan::call('cache:clear'); Artisan::call('cache:clear');
@ -33,9 +33,11 @@ Route::prefix('v1')->name('v1.')->group(
return 'xShop api v1'; return 'xShop api v1';
}); });
Route::get('states', [\App\Http\Controllers\Api\StateController::class,'index'])->name('state.index'); Route::get('states', [\App\Http\Controllers\Api\StateController::class, 'index'])->name('state.index');
Route::get('state/{state}', [\App\Http\Controllers\Api\StateController::class,'show'])->name('state.show'); Route::get('state/{state}', [\App\Http\Controllers\Api\StateController::class, 'show'])->name('state.show');
Route::get('category/props/{category}', [\App\Http\Controllers\Api\CategoryController::class,'props'])->name('category.prop'); Route::get('category/props/{category}', [\App\Http\Controllers\Api\CategoryController::class, 'props'])->name('category.prop');
Route::post('morph/search', [\App\Http\Controllers\Api\MorphController::class,'search'])->name('morph.search'); Route::post('morph/search', [\App\Http\Controllers\Api\MorphController::class, 'search'])->name('morph.search');
Route::post('visitor/display', [\App\Http\Controllers\Api\VisitorController::class,'display'])->name('visitor.display'); Route::post('visitor/display', [\App\Http\Controllers\Api\VisitorController::class, 'display'])->name('visitor.display');
Route::apiResource('web', \App\Http\Controllers\Api\Web\HomeController::class)->only('index');
}); });

Loading…
Cancel
Save