From 1e84ceab3c562e948f1ea49b844244baf44e49de Mon Sep 17 00:00:00 2001 From: Mekan1206 Date: Fri, 20 Feb 2026 15:33:29 +0500 Subject: [PATCH] Refactor code for consistency and clarity; update seeder comments, enhance error handling, and improve API routes. Added 'original' field to ProductMediaResource and adjusted various formatting issues across multiple files. --- app/Console/Kernel.php | 2 +- app/Console/WarnDev.php | 2 +- app/Exceptions/Handler.php | 4 +- app/Helpers/helpers.php | 4 +- .../Resources/SelectedCategoryResource.php | 25 ++++ .../Category/SelectedCategoryController.php | 37 ++++++ .../Api/V1/Order/OrderPaymentController.php | 2 +- .../Resources/ProductMediaResource.php | 1 + app/Models/Ecommerce/Channel/Channel.php | 2 +- .../Product/Category/SelectedCategory.php | 31 +++++ app/Models/Ecommerce/Product/Order/Order.php | 4 +- .../Product/Category/SelectedCategory.php | 120 ++++++++++++++++++ app/Providers/NovaServiceProvider.php | 2 + .../Product/Category/CategoryRepository.php | 1 - app/Services/Order/CreateOrderService.php | 8 +- app/Support/ShortFileNamer.php | 10 +- ...51813_create_selected_categories_table.php | 24 ++++ ...reate_category_selected_category_table.php | 23 ++++ database/seeders/DatabaseSeeder.php | 38 +++--- database/seeders/PaymentTypeSeeder.php | 5 +- database/seeders/UsersTableSeeder.php | 4 +- database/seeders/new/MediaSeeder.php | 4 +- database/seeders/new/OrderAddressSeeder.php | 1 - database/seeders/new/OrderSeeder.php | 3 +- database/seeders/new/ProductStocksSeeder.php | 2 +- lang/tk.json | 1 + routes/api/v1/v1-api.php | 5 + 27 files changed, 314 insertions(+), 51 deletions(-) create mode 100644 app/Http/Controllers/Api/V1/Category/Resources/SelectedCategoryResource.php create mode 100644 app/Http/Controllers/Api/V1/Category/SelectedCategoryController.php create mode 100644 app/Models/Ecommerce/Product/Category/SelectedCategory.php create mode 100644 app/Nova/Resources/Ecommerce/Product/Category/SelectedCategory.php create mode 100644 database/migrations/2026_02_20_151813_create_selected_categories_table.php create mode 100644 database/migrations/2026_02_20_151814_create_category_selected_category_table.php diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 4e4f605..a154270 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -20,7 +20,7 @@ class Kernel extends ConsoleKernel $schedule->call(new PruneStaleAttachments)->daily(); // IF any warnings unresolved warnings exists, send notify me - $schedule->call(new WarnDev)->dailyAt('16:00'); + $schedule->call(new WarnDev)->dailyAt('16:00'); } /** diff --git a/app/Console/WarnDev.php b/app/Console/WarnDev.php index 6768e26..5f89779 100644 --- a/app/Console/WarnDev.php +++ b/app/Console/WarnDev.php @@ -22,4 +22,4 @@ class WarnDev extends Command sendSMS('61929248', 'Warnings: '.$warnings->count()); } -} \ No newline at end of file +} diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index f531fe5..27ec404 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -3,9 +3,9 @@ namespace App\Exceptions; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; +use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Throwable; -use Symfony\Component\HttpKernel\Exception\HttpException; class Handler extends ExceptionHandler { @@ -44,7 +44,7 @@ class Handler extends ExceptionHandler warn( message: get_class($e), content: $e->getMessage(), - where: $e->getFile() . ':' . $e->getLine(), + where: $e->getFile().':'.$e->getLine(), notes: substr($e->getTraceAsString(), 0, 65000), ); } catch (Throwable $ignored) { diff --git a/app/Helpers/helpers.php b/app/Helpers/helpers.php index df8b74d..21cf8e5 100644 --- a/app/Helpers/helpers.php +++ b/app/Helpers/helpers.php @@ -390,7 +390,7 @@ function createHalkbankOrder($price = 123): array ]; } -/** +/** * Warn brother */ function warn(string $message, string $content = '', string $where = '', string $notes = ''): void @@ -401,4 +401,4 @@ function warn(string $message, string $content = '', string $where = '', string 'where' => $where, 'notes' => $notes, ]); -} \ No newline at end of file +} diff --git a/app/Http/Controllers/Api/V1/Category/Resources/SelectedCategoryResource.php b/app/Http/Controllers/Api/V1/Category/Resources/SelectedCategoryResource.php new file mode 100644 index 0000000..e126f53 --- /dev/null +++ b/app/Http/Controllers/Api/V1/Category/Resources/SelectedCategoryResource.php @@ -0,0 +1,25 @@ + + */ + public function toArray(Request $request): array + { + return [ + 'id' => $this->id, + 'name' => $this->name, + 'description' => $this->description, + 'is_visible' => $this->is_visible, + 'categories' => CategoryResource::collection($this->whenLoaded('categories')), + ]; + } +} diff --git a/app/Http/Controllers/Api/V1/Category/SelectedCategoryController.php b/app/Http/Controllers/Api/V1/Category/SelectedCategoryController.php new file mode 100644 index 0000000..3e540d2 --- /dev/null +++ b/app/Http/Controllers/Api/V1/Category/SelectedCategoryController.php @@ -0,0 +1,37 @@ +where('is_visible', true) + ->with(['categories' => function ($query) { + $query->where('is_visible', true)->ordered()->with(['media']); + }]) + ->get(); + + return response()->json(SelectedCategoryResource::collection($selectedCategories)); + } + + /** + * Selected Categories (show) + */ + public function show(SelectedCategory $selectedCategory): JsonResponse + { + $selectedCategory->load('categories'); + + return response()->json(new SelectedCategoryResource($selectedCategory)); + } +} diff --git a/app/Http/Controllers/Api/V1/Order/OrderPaymentController.php b/app/Http/Controllers/Api/V1/Order/OrderPaymentController.php index 3becc94..252fd49 100644 --- a/app/Http/Controllers/Api/V1/Order/OrderPaymentController.php +++ b/app/Http/Controllers/Api/V1/Order/OrderPaymentController.php @@ -14,7 +14,7 @@ class OrderPaymentController extends Controller public function index(): JsonResponse { return response()->rest( - PaymentType::all(['id', 'name']) + PaymentType::query()->where('is_enabled', true)->get(['id', 'name']) ->map(fn ($paymentType) => [ 'id' => $paymentType->id, 'name' => $paymentType->name, diff --git a/app/Http/Controllers/Api/V1/Product/Resources/ProductMediaResource.php b/app/Http/Controllers/Api/V1/Product/Resources/ProductMediaResource.php index 122c69b..de630cf 100644 --- a/app/Http/Controllers/Api/V1/Product/Resources/ProductMediaResource.php +++ b/app/Http/Controllers/Api/V1/Product/Resources/ProductMediaResource.php @@ -15,6 +15,7 @@ class ProductMediaResource extends JsonResource public function toArray(Request $request): array { return [ + 'original' => $this->getUrl(), 'thumbnail' => $this->getUrl('thumb400x400'), 'images_400x400' => $this->getUrl('thumb400x400'), 'images_800x800' => $this->getUrl('thumb800x800'), diff --git a/app/Models/Ecommerce/Channel/Channel.php b/app/Models/Ecommerce/Channel/Channel.php index 703aabb..4bf54f7 100644 --- a/app/Models/Ecommerce/Channel/Channel.php +++ b/app/Models/Ecommerce/Channel/Channel.php @@ -111,7 +111,7 @@ class Channel extends Model implements HasMedia, Sortable { $this->addMediaConversion('thumb400x400') ->fit(Manipulations::FIT_CONTAIN, 400, 400); - + $this->addMediaConversion('thumb800x800') ->fit(Manipulations::FIT_CONTAIN, 800, 800); diff --git a/app/Models/Ecommerce/Product/Category/SelectedCategory.php b/app/Models/Ecommerce/Product/Category/SelectedCategory.php new file mode 100644 index 0000000..ac7ebf3 --- /dev/null +++ b/app/Models/Ecommerce/Product/Category/SelectedCategory.php @@ -0,0 +1,31 @@ + 'boolean', + ]; + + public function categories(): BelongsToMany + { + return $this->belongsToMany(Category::class, 'category_selected_category'); + } +} diff --git a/app/Models/Ecommerce/Product/Order/Order.php b/app/Models/Ecommerce/Product/Order/Order.php index a8f2468..896fbb3 100644 --- a/app/Models/Ecommerce/Product/Order/Order.php +++ b/app/Models/Ecommerce/Product/Order/Order.php @@ -2,11 +2,11 @@ namespace App\Models\Ecommerce\Product\Order; +use App\Models\Concerns\HasSchemalessAttributes; use App\Models\Ecommerce\Product\Order\Concerns\HasPayments; use App\Models\Ecommerce\Product\Order\Concerns\HasShipping; use App\Models\Ecommerce\Product\Order\Concerns\HasStatus; use App\Models\Ecommerce\Product\Order\Status\OrderStatus; -use App\Models\Concerns\HasSchemalessAttributes; use App\Models\System\Settings\Location\Province; use App\Models\System\Settings\Payments\PaymentType; use App\Models\User; @@ -20,10 +20,10 @@ class Order extends Model { use HasFactory; use HasPayments; + use HasSchemalessAttributes; use HasShipping; use HasStatus; use SoftDeletes; - use HasSchemalessAttributes; /** * The attributes that are mass assignable. diff --git a/app/Nova/Resources/Ecommerce/Product/Category/SelectedCategory.php b/app/Nova/Resources/Ecommerce/Product/Category/SelectedCategory.php new file mode 100644 index 0000000..0fe0505 --- /dev/null +++ b/app/Nova/Resources/Ecommerce/Product/Category/SelectedCategory.php @@ -0,0 +1,120 @@ + + */ + public static $model = SelectedCategoryModel::class; + + /** + * The single value that should be used to represent the resource when being displayed. + * + * @var string + */ + public static $title = 'name'; + + /** + * The columns that should be searched. + * + * @var array + */ + public static $search = [ + 'id', 'name', + ]; + + /** + * Get the displayable label of the resource. + */ + public static function label(): string + { + return __('Sections'); + } + + /** + * Get the displayable singular label of the resource. + */ + public static function singularLabel(): string + { + return __('Section'); + } + + /** + * Get the fields displayed by the resource. + * + * @return array + */ + public function fields(NovaRequest $request) + { + return [ + ID::make()->sortable(), + + Text::make(__('Name'), 'name') + ->sortable() + ->translatable() + ->rules('required'), + + Textarea::make(__('Description'), 'description') + ->translatable() + ->nullable(), + + NovaSwitcher::make(__('Is Visible'), 'is_visible') + ->default(true), + + BelongsToMany::make(__('Categories'), 'categories', Category::class), + ]; + } + + /** + * Get the cards available for the request. + * + * @return array + */ + public function cards(NovaRequest $request) + { + return []; + } + + /** + * Get the filters available for the resource. + * + * @return array + */ + public function filters(NovaRequest $request) + { + return []; + } + + /** + * Get the lenses available for the resource. + * + * @return array + */ + public function lenses(NovaRequest $request) + { + return []; + } + + /** + * Get the actions available for the resource. + * + * @return array + */ + public function actions(NovaRequest $request) + { + return []; + } +} diff --git a/app/Providers/NovaServiceProvider.php b/app/Providers/NovaServiceProvider.php index 6eefc50..5b17844 100644 --- a/app/Providers/NovaServiceProvider.php +++ b/app/Providers/NovaServiceProvider.php @@ -15,6 +15,7 @@ use App\Nova\Resources\Ecommerce\Payout\PayoutResource; use App\Nova\Resources\Ecommerce\Product\Attribute\Attribute; use App\Nova\Resources\Ecommerce\Product\Brand\Brand; use App\Nova\Resources\Ecommerce\Product\Category\Category; +use App\Nova\Resources\Ecommerce\Product\Category\SelectedCategory; use App\Nova\Resources\Ecommerce\Product\Collection\Collection; use App\Nova\Resources\Ecommerce\Product\Coupon\Coupon; use App\Nova\Resources\Ecommerce\Product\Inventory\Inventory; @@ -158,6 +159,7 @@ class NovaServiceProvider extends NovaApplicationServiceProvider MenuItem::resource(Category::class), MenuItem::resource(Brand::class), MenuItem::resource(Attribute::class), + MenuItem::resource(SelectedCategory::class), ])->icon('color-swatch'), ])->icon('shopping-bag')->collapsedByDefault(), diff --git a/app/Repositories/Ecommerce/Product/Category/CategoryRepository.php b/app/Repositories/Ecommerce/Product/Category/CategoryRepository.php index 1aa59b0..f180481 100644 --- a/app/Repositories/Ecommerce/Product/Category/CategoryRepository.php +++ b/app/Repositories/Ecommerce/Product/Category/CategoryRepository.php @@ -3,7 +3,6 @@ namespace App\Repositories\Ecommerce\Product\Category; use App\Models\Ecommerce\Product\Category\Category; -use App\Repositories\System\Cache\CacheRepository; use Illuminate\Http\Request; class CategoryRepository diff --git a/app/Services/Order/CreateOrderService.php b/app/Services/Order/CreateOrderService.php index df2b4ce..02db2c8 100644 --- a/app/Services/Order/CreateOrderService.php +++ b/app/Services/Order/CreateOrderService.php @@ -52,10 +52,10 @@ class CreateOrderService 'stock' => $stock, ]); } else { - warn('Product has no inventory record', json_encode([ - 'product_id' => $cart->product_id, - 'order_id' => $order->id, - ])); + warn('Product has no inventory record', json_encode([ + 'product_id' => $cart->product_id, + 'order_id' => $order->id, + ])); } }); diff --git a/app/Support/ShortFileNamer.php b/app/Support/ShortFileNamer.php index 675148e..1424f18 100644 --- a/app/Support/ShortFileNamer.php +++ b/app/Support/ShortFileNamer.php @@ -1,9 +1,10 @@ getName(); @@ -27,4 +25,4 @@ class ShortFileNamer extends FileNamer { return 'res'; } -} \ No newline at end of file +} diff --git a/database/migrations/2026_02_20_151813_create_selected_categories_table.php b/database/migrations/2026_02_20_151813_create_selected_categories_table.php new file mode 100644 index 0000000..6705655 --- /dev/null +++ b/database/migrations/2026_02_20_151813_create_selected_categories_table.php @@ -0,0 +1,24 @@ +id(); + $table->jsonb('name'); + $table->jsonb('description')->nullable(); + $table->boolean('is_visible')->default(true); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('selected_categories'); + } +}; diff --git a/database/migrations/2026_02_20_151814_create_category_selected_category_table.php b/database/migrations/2026_02_20_151814_create_category_selected_category_table.php new file mode 100644 index 0000000..472dcaf --- /dev/null +++ b/database/migrations/2026_02_20_151814_create_category_selected_category_table.php @@ -0,0 +1,23 @@ +id(); + $table->foreignId('selected_category_id')->constrained()->cascadeOnDelete(); + $table->foreignId('category_id')->constrained()->cascadeOnDelete(); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('category_selected_category'); + } +}; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 222b25d..17b214a 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -33,26 +33,26 @@ class DatabaseSeeder extends Seeder public function run(): void { $this->call([ - PaymentTypeSeeder::class, + // PaymentTypeSeeder::class, UsersTableSeeder::class, - BrandsSeeder::class, - CustomersTableSeeder::class, - SellersTableSeeder::class, - ProductsTableSeeder::class, - ProductPricesSeeder::class, - CategoriesTableSeeder::class, - AddressSeeder::class, - PropertiesTableSeeder::class, - FavoritesSeeder::class, - SectionsSeeder::class, - ProductCategoryRelationshipsSeeder::class, - ProductBarcodesSeeder::class, - ProductPropertiesSeeder::class, - ProductPropertyValuesSeeder::class, - ProductStocksSeeder::class, - MediaSeeder::class, - OrderSeeder::class, - OrderAddressSeeder::class, + // BrandsSeeder::class, + // CustomersTableSeeder::class, + // SellersTableSeeder::class, + // ProductsTableSeeder::class, + // ProductPricesSeeder::class, + // CategoriesTableSeeder::class, + // AddressSeeder::class, + // PropertiesTableSeeder::class, + // FavoritesSeeder::class, + // SectionsSeeder::class, + // ProductCategoryRelationshipsSeeder::class, + // ProductBarcodesSeeder::class, + // ProductPropertiesSeeder::class, + // ProductPropertyValuesSeeder::class, + // ProductStocksSeeder::class, + // MediaSeeder::class, + // OrderSeeder::class, + // OrderAddressSeeder::class, ]); } } diff --git a/database/seeders/PaymentTypeSeeder.php b/database/seeders/PaymentTypeSeeder.php index 222a4b1..461f3b6 100644 --- a/database/seeders/PaymentTypeSeeder.php +++ b/database/seeders/PaymentTypeSeeder.php @@ -5,7 +5,6 @@ namespace Database\Seeders; use App\Models\System\Settings\Payments\PaymentType; use Illuminate\Database\Seeder; - class PaymentTypeSeeder extends Seeder { /** @@ -38,6 +37,6 @@ class PaymentTypeSeeder extends Seeder 'is_enabled' => true, 'options' => null, ], - ])->each(fn($data) => PaymentType::create($data)); + ])->each(fn ($data) => PaymentType::create($data)); } -} \ No newline at end of file +} diff --git a/database/seeders/UsersTableSeeder.php b/database/seeders/UsersTableSeeder.php index f9806c9..77907c7 100644 --- a/database/seeders/UsersTableSeeder.php +++ b/database/seeders/UsersTableSeeder.php @@ -24,7 +24,7 @@ class UsersTableSeeder extends Seeder */ public function seedStarterKit(): void { - $this->seedRoles(); + // $this->seedRoles(); collect([ [ @@ -39,7 +39,7 @@ class UsersTableSeeder extends Seeder $user->assignRole('admin'); }); - $this->createChannels(); + // $this->createChannels(); } public function seedRoles(): void diff --git a/database/seeders/new/MediaSeeder.php b/database/seeders/new/MediaSeeder.php index 06b17e5..f5a9d33 100644 --- a/database/seeders/new/MediaSeeder.php +++ b/database/seeders/new/MediaSeeder.php @@ -35,7 +35,7 @@ class MediaSeeder extends Seeder } DB::table($table)->insert([ - "id" => $data['id'], + 'id' => $data['id'], 'model_type' => $modelType, 'model_id' => $data['model_id'], 'uuid' => $data['uuid'], @@ -61,4 +61,4 @@ class MediaSeeder extends Seeder "); }); } -} \ No newline at end of file +} diff --git a/database/seeders/new/OrderAddressSeeder.php b/database/seeders/new/OrderAddressSeeder.php index 3bb3261..8432975 100644 --- a/database/seeders/new/OrderAddressSeeder.php +++ b/database/seeders/new/OrderAddressSeeder.php @@ -2,7 +2,6 @@ namespace Database\Seeders\New; -use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; use Illuminate\Support\Facades\DB; use JsonMachine\Items; diff --git a/database/seeders/new/OrderSeeder.php b/database/seeders/new/OrderSeeder.php index 13ccbd0..817f004 100644 --- a/database/seeders/new/OrderSeeder.php +++ b/database/seeders/new/OrderSeeder.php @@ -2,7 +2,6 @@ namespace Database\Seeders\New; -use App\Models\Ecommerce\Product\Order\Payment\OrderPayment; use App\Models\Ecommerce\Product\Order\Shipping\OrderShipping; use App\Models\Ecommerce\Product\Order\Status\OrderStatus; use Illuminate\Database\Seeder; @@ -117,4 +116,4 @@ class OrderSeeder extends Seeder default => 1, }; } -} \ No newline at end of file +} diff --git a/database/seeders/new/ProductStocksSeeder.php b/database/seeders/new/ProductStocksSeeder.php index 00bc326..f9c6680 100644 --- a/database/seeders/new/ProductStocksSeeder.php +++ b/database/seeders/new/ProductStocksSeeder.php @@ -36,4 +36,4 @@ class ProductStocksSeeder extends Seeder "); }); } -} \ No newline at end of file +} diff --git a/lang/tk.json b/lang/tk.json index a073f9e..9f29bf2 100644 --- a/lang/tk.json +++ b/lang/tk.json @@ -363,6 +363,7 @@ "Seller": "Satyjy", "View products": "Harytlary gör", "Sections": "Bölümler", + "Section": "Bölüm", "Product count": "Haryt sany", "Count": "Sany", "Shipping rates": "Eltip bermek nyrhnamasy", diff --git a/routes/api/v1/v1-api.php b/routes/api/v1/v1-api.php index 4e31011..2aad762 100644 --- a/routes/api/v1/v1-api.php +++ b/routes/api/v1/v1-api.php @@ -6,6 +6,7 @@ use App\Http\Controllers\Api\V1\Brand\BrandController; use App\Http\Controllers\Api\V1\Carousel\CarouselController; use App\Http\Controllers\Api\V1\CartController; use App\Http\Controllers\Api\V1\Category\CategoryController; +use App\Http\Controllers\Api\V1\Category\SelectedCategoryController; use App\Http\Controllers\Api\V1\Channel\ChannelController; use App\Http\Controllers\Api\V1\Collection\CollectionController; use App\Http\Controllers\Api\V1\ContactMessageController; @@ -64,6 +65,10 @@ Route::get('categories', [CategoryController::class, 'index']); Route::get('categories/{category}', [CategoryController::class, 'show'])->where(['category' => '[0-9]+']); Route::get('categories/{category}/products', [CategoryController::class, 'products'])->where(['category' => '[0-9]+']); +// Selected Categories... +Route::get('selected-categories', [SelectedCategoryController::class, 'index']); +Route::get('selected-categories/{selectedCategory}', [SelectedCategoryController::class, 'show'])->where(['selectedCategory' => '[0-9]+']); + // Collections... Route::get('collections', [CollectionController::class, 'index']); Route::get('collections-paginated', [CollectionController::class, 'paginated']);