test
@@ -24,11 +24,11 @@ class Controller extends ExController
|
|||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$this->authorize('view', 'categories');
|
$this->authorize('view', 'categories');
|
||||||
$categories = Category::select('id', 'name->ru as category', 'position', 'parent_id')
|
$categories = Category::select('id', 'name->ru as category', 'position', 'parent_id', 'image')
|
||||||
->where('parent_id', null)
|
->where('parent_id', null)
|
||||||
->with(['children' => function ($parent) {
|
->with(['children' => function ($parent) {
|
||||||
return $parent->select('id', 'name->ru as category', 'parent_id', 'position')->orderBy('position', 'asc')->with(['children' => function ($parent) {
|
return $parent->select('id', 'name->ru as category', 'parent_id', 'position', 'image')->orderBy('position', 'asc')->with(['children' => function ($parent) {
|
||||||
return $parent->select('id', 'name->ru as category', 'parent_id', 'position')->orderBy('position', 'asc');
|
return $parent->select('id', 'name->ru as category', 'parent_id', 'position', 'image')->orderBy('position', 'asc');
|
||||||
}]);
|
}]);
|
||||||
}])->orderBy('position', 'asc')->get();
|
}])->orderBy('position', 'asc')->get();
|
||||||
|
|
||||||
@@ -102,11 +102,7 @@ class Controller extends ExController
|
|||||||
return view('dashboard.category.update', compact('parent_categories', 'category', 'brands'));
|
return view('dashboard.category.update', compact('parent_categories', 'category', 'brands'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->hasFile('image')) {
|
$image = $request->getImage($category);
|
||||||
$image = $request->file('image')->store('uploads/categories', 'local');
|
|
||||||
} else {
|
|
||||||
$image = $category->image;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->dispatchSync(new UpdateJob($category, $request, $image));
|
$this->dispatchSync(new UpdateJob($category, $request, $image));
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ class Category extends Model
|
|||||||
'is_filter_power' => 'boolean'
|
'is_filter_power' => 'boolean'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
protected $appends = ['image_url'];
|
||||||
|
|
||||||
protected $hidden = [
|
protected $hidden = [
|
||||||
'created_at',
|
'created_at',
|
||||||
'updated_at'
|
'updated_at'
|
||||||
@@ -137,6 +139,11 @@ class Category extends Model
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getImageUrlAttribute(): string
|
||||||
|
{
|
||||||
|
return $this->getImage();
|
||||||
|
}
|
||||||
|
|
||||||
public function getImage(): string
|
public function getImage(): string
|
||||||
{
|
{
|
||||||
if (!in_array($this->image, ['null', null])) {
|
if (!in_array($this->image, ['null', null])) {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
date_default_timezone_set('Asia/Tashkent');
|
date_default_timezone_set('Asia/Tashkent');
|
||||||
// set lang to uz
|
// set lang to uz
|
||||||
if (App::environment(['staging', 'production'])) {
|
if (App::environment(['staging', 'production'])) {
|
||||||
URL::forceScheme('https');
|
URL::forceScheme('http');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
82
deployment_guide.md
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
# Production Deployment Guide
|
||||||
|
|
||||||
|
Ushbu yo'riqnoma local o'zgarishlarni (MinIO va API ulanishlari) serverga (Production) ko'chirish uchun kerakli qadamlarni o'z ichiga oladi.
|
||||||
|
|
||||||
|
## 1. Backend (Laravel) - `api.quyoshli.uz`
|
||||||
|
|
||||||
|
Serverga kirib, loyiha papkasida quyidagi ishlarni bajaring:
|
||||||
|
|
||||||
|
### `.env` faylini yangilash
|
||||||
|
Production serverda local MinIO emas, balki **haqiqiy masofaviy MinIO** ma'lumotlari bo'lishi kerak:
|
||||||
|
```env
|
||||||
|
FILESYSTEM_DISK=s3
|
||||||
|
AWS_USE_PATH_STYLE_ENDPOINT=false
|
||||||
|
|
||||||
|
MINIO_ACCESS_KEY=1121RspAhfuxdjqCrkXH
|
||||||
|
MINIO_SECRET_KEY=97rvdUg266dIAseFKeJ3l2cHRavRmCrhEDQTvaDH
|
||||||
|
MINIO_BUCKET=quyoshli
|
||||||
|
MINIO_ENDPOINT=https://minio.quyoshli.uz
|
||||||
|
```
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> Masofaviy MinIO-da `AWS_USE_PATH_STYLE_ENDPOINT=false` bo'lishi mumkin (sozlamaga qarab), lekin odatda HTTPS endpointlar uchun `false` ishlatiladi.
|
||||||
|
|
||||||
|
### Buyruqlar ketma-ketligi
|
||||||
|
```bash
|
||||||
|
# Kodni yangilash
|
||||||
|
git pull origin main
|
||||||
|
|
||||||
|
# Bog'liqliklarni o'rnatish
|
||||||
|
composer install --no-dev --optimize-autoloader
|
||||||
|
|
||||||
|
# Ma'lumotlar bazasini yangilash
|
||||||
|
php artisan migrate --force
|
||||||
|
|
||||||
|
# Keshni tozalash va optimizatsiya
|
||||||
|
php artisan optimize
|
||||||
|
php artisan config:cache
|
||||||
|
php artisan view:cache
|
||||||
|
|
||||||
|
# Frontend assetlarni yig'ish (agar Laravel Vite ishlatilsa)
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ruxsatnomalar (Permissions)
|
||||||
|
Serverda papkalarga to'g'ri ruxsat berish juda muhim:
|
||||||
|
```bash
|
||||||
|
sudo chown -R www-data:www-data storage bootstrap/cache public/uploads
|
||||||
|
sudo chmod -R 775 storage bootstrap/cache public/uploads
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Frontend (Next.js) - `getgreen.uz`
|
||||||
|
|
||||||
|
Frontend loyihasida `.env` faylini quyidagicha sozlashingiz kerak:
|
||||||
|
|
||||||
|
### `.env` fayli
|
||||||
|
```env
|
||||||
|
API_URL=https://api.quyoshli.uz/api
|
||||||
|
PORT=3000
|
||||||
|
```
|
||||||
|
|
||||||
|
### Qayta qurish (Rebuild)
|
||||||
|
Agar Docker ishlatayotgan bo'lsangiz:
|
||||||
|
```bash
|
||||||
|
docker-compose up -d --build
|
||||||
|
```
|
||||||
|
Agar Docker-siz bo'lsa:
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
pm2 restart all # yoki boshqa process manager
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. MinIO Sozlamalari (Masofaviy)
|
||||||
|
Masofaviy MinIO serveringizda `quyoshli` bucket-i yaratilganiga va ruxsatnomalari (Policy) to'g'ri sozlanganiga ishonch hosil qiling:
|
||||||
|
- Rasmlar hamma uchun ochiq bo'lishi uchun Bucket Policy-ni **Public** yoki **Read-only** qilib sozlash tavsiya etiladi.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> Agar rasmlar production-da ko'rinmasa, `.env` faylidagi `AWS_USE_PATH_STYLE_ENDPOINT` qiymatini `true` yoki `false` qilib almashtirib ko'ring.
|
||||||
0
public/uploads/calc/2026/04/15/YyqWQsuViSt04C9Wdty66GljQvCCWFkpLqLHMS8N.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 151 KiB |
0
public/uploads/posters/2026/04/15/TrLZTb7KVgadw1yLaKzInuv4BecNYTwwRilUkfwy.png
Normal file → Executable file
|
Before Width: | Height: | Size: 146 KiB After Width: | Height: | Size: 146 KiB |
0
public/uploads/posters/thumbs/2026/04/15/TrLZTb7KVgadw1yLaKzInuv4BecNYTwwRilUkfwy.png
Normal file → Executable file
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
0
public/uploads/screens/2026/04/15/hi4Ts1no1D6bCvqGT6sx46zpWVNaL9NnuTCHG3bS.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 1.9 MiB |
0
public/uploads/screens/thumbs/2026/04/15/hi4Ts1no1D6bCvqGT6sx46zpWVNaL9NnuTCHG3bS.png
Normal file → Executable file
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
@@ -71,9 +71,10 @@
|
|||||||
></i>
|
></i>
|
||||||
|
|
||||||
</b>
|
</b>
|
||||||
<span>
|
<span class="d-flex align-items-center">
|
||||||
<b>ID: {{ data.id }} </b>
|
<b>ID: {{ data.id }} </b>
|
||||||
{{ data.category }}
|
<img v-if="data.image_url" :src="data.image_url" style="width: 30px; height: 30px; object-fit: cover; margin-left: 10px; border-radius: 4px;" alt="">
|
||||||
|
<span class="ml-1">{{ data.category }}</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div class="ml-auto">
|
<div class="ml-auto">
|
||||||
|
|||||||
@@ -130,7 +130,7 @@
|
|||||||
width: 300px;
|
width: 300px;
|
||||||
height: auto;
|
height: auto;
|
||||||
"
|
"
|
||||||
:src="category.image"
|
:src="category.image_url"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||