Files
3dealer/resources/views/components/product-custom-fields.blade.php
T

89 lines
4.4 KiB
PHP
Raw Normal View History

2026-09-23 17:53:23 +03:00
{{--
<x-product-custom-fields :fields="$product['custom_fields']" />
The product's custom fields (boboko-core's Product::$custom_fields), rendered
inside the add-to-cart <form> so their values travel with it as
custom_fields[key]. text → input, textarea → textarea, file → photo upload.
The label is styled like the product option labels (option-buttons /
color-swatch); the optional help_text shows under it. Help text is
product-page only; the cart/checkout line meta only snapshots the label.
2026-09-23 17:53:23 +03:00
A photo is uploaded as soon as it's picked (custom-field-upload-controller.js)
2026-09-25 13:47:58 +03:00
and only the resulting File row's id (boboko-core's Modules\Core\File\
Models\File) is submitted with the form — the file input itself has no
name. It still carries `required`, so the browser's own validation blocks
add-to-cart until a photo is picked, and the controller marks it invalid
(setCustomValidity) while the upload is in flight.
2026-09-23 17:53:23 +03:00
--}}
@props(['fields' => []])
@use('App\Http\Controllers\CustomFieldUploadController')
<div class="flex flex-col gap-6">
@foreach ($fields as $field)
@php
$id = 'custom-field-'.$field['key'];
$name = 'custom_fields['.$field['key'].']';
$required = (bool) ($field['required'] ?? false);
$hint = filled($field['help_text'] ?? null) ? $field['help_text'] : null;
// mb-1 on top of the field's gap-2 matches the option labels' mb-3;
// with a hint, the label + hint group carries that spacing instead.
$labelClass = 'font-bold text-sm uppercase tracking-wide'.($hint ? '' : ' mb-1');
$hintId = $hint ? $id.'-hint' : null;
2026-09-23 17:53:23 +03:00
@endphp
@switch($field['type'])
@case('textarea')
<x-ui.field :label="$field['label']" :label-class="$labelClass" :hint="$hint" :for="$id" :required="$required">
<x-ui.textarea :id="$id" :name="$name" :required="$required" :rows="4" maxlength="2000" :aria-describedby="$hintId" />
2026-09-23 17:53:23 +03:00
</x-ui.field>
@break
@case('file')
<x-ui.field
:label="$field['label']"
:label-class="$labelClass"
:hint="$hint"
2026-09-23 17:53:23 +03:00
:for="$id"
:required="$required"
:description="__('storefront.product.custom_field_photo_hint', ['size' => CustomFieldUploadController::MAX_KILOBYTES / 1024])"
data-controller="custom-field-upload"
data-custom-field-upload-url-value="{{ route('custom-field-upload.store') }}"
data-custom-field-upload-label-value="{{ $field['label'] }}"
data-custom-field-upload-uploading-message-value="{{ __('storefront.product.custom_field_uploading') }}"
data-custom-field-upload-failed-message-value="{{ __('storefront.product.custom_field_upload_failed') }}"
>
<input type="hidden" name="{{ $name }}" data-custom-field-upload-target="reference">
<x-ui.file-input
:id="$id"
:accept="CustomFieldUploadController::accept()"
:required="$required"
aria-describedby="{{ $hintId ? $hintId.' ' : '' }}{{ $id }}-description {{ $id }}-error"
2026-09-23 17:53:23 +03:00
data-custom-field-upload-target="file"
data-action="change->custom-field-upload#upload"
/>
<img
alt=""
width="96"
height="96"
hidden
class="w-24 h-24 object-cover border border-black"
data-custom-field-upload-target="preview"
data-action="error->custom-field-upload#hidePreview"
>
<p id="{{ $id }}-error" class="text-sm text-red-600" role="alert" hidden data-custom-field-upload-target="error"></p>
</x-ui.field>
@break
@default
<x-ui.field :label="$field['label']" :label-class="$labelClass" :hint="$hint" :for="$id" :required="$required">
<x-ui.input :id="$id" :name="$name" :required="$required" maxlength="255" :aria-describedby="$hintId" />
2026-09-23 17:53:23 +03:00
</x-ui.field>
@endswitch
@endforeach
</div>