03f8caf3e9
後端 - 新增 6 個 Notification class(預約建立/確認/拒絕/取消/完成、收到評價),database + mail 雙 channel - 新增 NotificationController(list / unread-count / markRead / markAllRead / destroy) - 整合通知觸發至 MemberBookingController、ProviderBookingController、CompleteFinishedBookings、ReviewController - 新增 notifications / jobs / failed_jobs migration - Docker Compose 加入 queue-worker、mailpit service - DivingOffer 補上 provider() 關聯 前端 - 新增 notificationStore(Polling 30s/60s 自適應 + Page Visibility API) - 新增 NotificationBell(未讀 Badge)、NotificationDrawer(側邊通知中心) - main.js:auth store init 前置於 router.use(),修正 beforeEach guard 時序問題 - notificationAxios:依路徑動態選擇 member/coach token - NotificationDrawer:改用 new URL().pathname 提取 action_url 路徑 OpenSpec - 歸檔 notification-system change - 同步 notification-core / notification-email / notification-triggers specs 至主規格 - 更新 booking-lifecycle / review-lifecycle spec(補充通知觸發 requirement) Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
71 lines
1.5 KiB
PHP
71 lines
1.5 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
class DivingOffer extends Model
|
|
{
|
|
public $timestamps = false;
|
|
|
|
protected $table = 'diving_offers';
|
|
|
|
protected $fillable = [
|
|
'provider_id',
|
|
'title',
|
|
'location',
|
|
'spot',
|
|
'rating',
|
|
'reviews',
|
|
'price',
|
|
'badges',
|
|
'description',
|
|
'tag',
|
|
'region',
|
|
'cover_image',
|
|
];
|
|
|
|
protected $casts = [
|
|
'badges' => 'array',
|
|
'rating' => 'float',
|
|
'price' => 'integer',
|
|
'reviews'=> 'integer',
|
|
];
|
|
|
|
protected static function booted(): void
|
|
{
|
|
static::deleting(function ($offer) {
|
|
Storage::disk('public')->deleteDirectory("offers/{$offer->id}");
|
|
});
|
|
}
|
|
|
|
public function getCoverImageUrlAttribute(): ?string
|
|
{
|
|
return $this->cover_image
|
|
? Storage::disk('public')->url($this->cover_image)
|
|
: null;
|
|
}
|
|
|
|
public function provider(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class, 'provider_id');
|
|
}
|
|
|
|
public function schedules()
|
|
{
|
|
return $this->hasMany(CourseSchedule::class, 'diving_offer_id');
|
|
}
|
|
|
|
public function courseImages()
|
|
{
|
|
return $this->hasMany(CourseImage::class)->orderBy('sort_order');
|
|
}
|
|
|
|
public function reviews()
|
|
{
|
|
return $this->hasMany(Review::class);
|
|
}
|
|
}
|