'GiftCard'. */ class GiftCard extends SettingListing { public static $meta_key = 'gift_card'; public static $table_name = 'restaurant_setting'; public static $pivot_tenant_field = 'restaurant_id'; public static $component_list_item = 'item-gift-card'; // Product types (how the voucher is sold). Map to Voucher model types: // fixed_amount + free_amount -> Voucher::TYPE_AMOUNT ; experience -> TYPE_EXPERIENCE const TYPE_FIXED_AMOUNT = 'fixed_amount'; // pre-set value (e.g. 50) const TYPE_FREE_AMOUNT = 'free_amount'; // buyer chooses between min and max const TYPE_EXPERIENCE = 'experience'; // set-price product (menu / experience) protected $casts = [ 'active' => 'boolean', ]; public static function description() { return __eva('Gift vouchers let customers buy credit or experiences online and redeem them when they book.'); } public function restaurant() { return $this->belongsTo(Restaurant::class); } public static function typeOptions() { return [ ['label' => __eva('Fixed amount'), 'value' => self::TYPE_FIXED_AMOUNT], ['label' => __eva('Free amount (buyer chooses)'), 'value' => self::TYPE_FREE_AMOUNT], ['label' => __eva('Experience / set price'), 'value' => self::TYPE_EXPERIENCE], ]; } public static function expiryOptions() { return [ ['label' => __eva('6 months'), 'value' => '6'], ['label' => __eva('12 months'), 'value' => '12'], ['label' => __eva('18 months'), 'value' => '18'], ['label' => __eva('24 months'), 'value' => '24'], ['label' => __eva('36 months'), 'value' => '36'], ['label' => __eva('No expiry'), 'value' => '0'], ]; } public function fields() { return [ [ 'attribute' => 'active', 'stacked' => true, 'style' => 'display: inline-block; width: 25%; vertical-align: top;', 'name' => __eva('Active'), 'component' => 'boolean-field', 'type' => 'switch', 'value' => $this->active, ], [ 'attribute' => 'name', 'stacked' => true, 'style' => 'display: inline-block; width: 75%;', 'inputClass' => 'form-input-bordered-highlight', 'name' => __eva('Name'), 'helpText' => __eva('Shown to the buyer, e.g. "50 Gift Card" or "Tasting Menu for Two"'), 'component' => 'text-field', 'value' => $this->name, ], [ 'attribute' => 'type', 'stacked' => true, 'name' => __eva('Type'), 'component' => 'select-field', 'options' => self::typeOptions(), 'value' => $this->type, ], [ 'attribute' => 'amount', 'stacked' => true, 'style' => 'display: inline-block; width: 33%;', 'name' => __eva('Amount'), 'helpText' => __eva('Used by "Fixed amount" and "Experience" types'), 'component' => 'text-field', 'value' => $this->amount, ], [ 'attribute' => 'amount_min', 'stacked' => true, 'style' => 'display: inline-block; width: 33%;', 'name' => __eva('Min amount'), 'helpText' => __eva('Used by "Free amount" type'), 'component' => 'text-field', 'value' => $this->amount_min, ], [ 'attribute' => 'amount_max', 'stacked' => true, 'style' => 'display: inline-block; width: 34%;', 'name' => __eva('Max amount'), 'helpText' => __eva('Used by "Free amount" type'), 'component' => 'text-field', 'value' => $this->amount_max, ], [ 'attribute' => 'expiry_months', 'stacked' => true, 'name' => __eva('Expiry'), 'helpText' => __eva('How long the voucher stays valid after purchase'), 'component' => 'select-field', 'options' => self::expiryOptions(), 'value' => $this->expiry_months, ], [ 'attribute' => 'public_description', 'stacked' => true, 'name' => __eva('Description'), 'helpText' => __eva('Shown to the buyer on the purchase page'), 'component' => 'textarea-field', 'value' => $this->public_description, ], [ 'attribute' => 'terms', 'stacked' => true, 'name' => __eva('Terms & conditions'), 'helpText' => __eva('Optional. Shown before purchase and on the voucher'), 'component' => 'textarea-field', 'value' => $this->terms, ], ]; } public function defaultValue() { return [ 'active' => true, 'name' => __eva('New gift voucher'), 'type' => self::TYPE_FIXED_AMOUNT, 'amount' => '50', 'amount_min' => '10', 'amount_max' => '500', 'expiry_months' => '12', 'public_description' => '', 'terms' => '', ]; } /** * Active gift voucher products of a restaurant, shaped for the public purchase * widget (the [rr_vouchers] shortcode localizes these). Only buyer-facing * fields — never the internal terms audit or expiry mechanics beyond months. */ public static function activeProducts($restaurantId) { $items = self::where(self::$pivot_tenant_field, $restaurantId)->get(); $out = []; foreach ($items as $item) { if (!$item->active) { continue; } $out[] = self::mapPublicProduct($item); } return $out; } /** * Buyer-facing shape of one gift card product (used by the [rr_voucher] * shortcode, which targets a single product by its restaurant_setting id). */ public static function mapPublicProduct($item) { return [ 'id' => intval($item->id), 'name' => $item->name, 'type' => $item->type, 'amount' => $item->amount, 'amount_min' => $item->amount_min, 'amount_max' => $item->amount_max, 'expiry_months' => $item->expiry_months, 'description' => $item->public_description, 'terms' => $item->terms, ]; } }