520 lines
30 KiB
PHP
520 lines
30 KiB
PHP
@extends('layouts.main')
|
|
|
|
@section('title')
|
|
{{ __('Custom Fields') }}
|
|
@endsection
|
|
|
|
@section('page-title')
|
|
<div class="page-title">
|
|
<div class="row">
|
|
<div class="col-12 col-md-6 order-md-1 order-last">
|
|
<h4>@yield('title')</h4>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endsection
|
|
|
|
@section('content')
|
|
<section class="section">
|
|
<div class="buttons">
|
|
<a class="btn btn-primary" href="{{ url('custom-fields') }}">
|
|
< {{ __('Back to Custom Fields') }} </a>
|
|
@if (in_array($custom_field->type, ['radio', 'checkbox', 'dropdown']))
|
|
<a class="btn btn-primary" data-bs-toggle="modal" data-bs-target='#addModal'>+
|
|
{{ __('Add Options') }}</a>
|
|
@endif
|
|
</div>
|
|
<form action="{{ route('custom-fields.update', $custom_field->id) }}" class="edit-form"
|
|
data-success-function="afterCustomFieldUpdate" method="POST" data-parsley-validate
|
|
enctype="multipart/form-data">
|
|
@method('PUT')
|
|
@csrf
|
|
<div class="row">
|
|
|
|
<div class="col-md-6 col-sm-12">
|
|
<div class="card">
|
|
<div class="card-header">{{ __('Edit Custom Field') }}</div>
|
|
<div class="card-body mt-2">
|
|
|
|
<ul class="nav nav-tabs" id="langTabs" role="tablist">
|
|
@foreach ($languages as $key => $lang)
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link @if ($key == 0) active @endif"
|
|
id="tab-{{ $lang->id }}" data-bs-toggle="tab"
|
|
data-bs-target="#lang-{{ $lang->id }}" type="button" role="tab">
|
|
{{ $lang->name }}
|
|
</button>
|
|
</li>
|
|
@endforeach
|
|
</ul>
|
|
|
|
<div class="tab-content mt-3">
|
|
@foreach ($languages as $key => $lang)
|
|
<div class="tab-pane fade @if ($key == 0) show active @endif"
|
|
id="lang-{{ $lang->id }}" role="tabpanel">
|
|
<input type="hidden" name="languages[]" value="{{ $lang->id }}">
|
|
|
|
<div class="form-group">
|
|
<label>{{ __('Field Name') }} ({{ $lang->name }})</label>
|
|
<input type="text" name="name[{{ $lang->id }}]" class="form-control"
|
|
value="{{ $translations[$lang->id]['name'] ?? '' }}"
|
|
@if ($lang->id == 1) @endif>
|
|
</div>
|
|
|
|
@if ($lang->id == 1)
|
|
{{-- Type (Only in English) - Read Only --}}
|
|
<div class="form-group">
|
|
<label>{{ __('Field Type') }}</label>
|
|
<select name="type" id="type" class="form-control" required
|
|
disabled>
|
|
<option value="number"
|
|
{{ $custom_field->type == 'number' ? 'selected' : '' }}>
|
|
{{ __('Number Input') }}</option>
|
|
<option value="textbox"
|
|
{{ $custom_field->type == 'textbox' ? 'selected' : '' }}>
|
|
{{ __('Text Input') }}</option>
|
|
<option value="fileinput"
|
|
{{ $custom_field->type == 'fileinput' ? 'selected' : '' }}>
|
|
{{ __('File Input') }}</option>
|
|
<option value="radio"
|
|
{{ $custom_field->type == 'radio' ? 'selected' : '' }}>
|
|
{{ __('Radio') }}</option>
|
|
<option value="dropdown"
|
|
{{ $custom_field->type == 'dropdown' ? 'selected' : '' }}>
|
|
{{ __('Dropdown') }}</option>
|
|
<option value="checkbox"
|
|
{{ $custom_field->type == 'checkbox' ? 'selected' : '' }}>
|
|
{{ __('Checkboxes') }}</option>
|
|
</select>
|
|
<input type="hidden" name="type" value="{{ $custom_field->type }}">
|
|
<small
|
|
class="text-muted">{{ __('Field type cannot be changed after creation.') }}</small>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6 form-group min-max-fields">
|
|
<label>{{ __('Field Length (Min)') }}</label>
|
|
<input type="number" name="min_length" class="form-control"
|
|
value="{{ $custom_field->min_length !== null ? $custom_field->min_length : '' }}" min="0">
|
|
</div>
|
|
<div class="col-md-6 form-group min-max-fields">
|
|
<label>{{ __('Field Length (Max)') }}</label>
|
|
<input type="number" name="max_length" class="form-control"
|
|
value="{{ $custom_field->max_length !== null ? $custom_field->max_length : '' }}" min="0">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<div class="col-md-12 form-group">
|
|
<label for="image"
|
|
class="form-label">{{ __('Icon ') }}</label>
|
|
<input type="file" name="image" id="image"
|
|
class="form-control" accept=" .jpg, .jpeg, .png, .svg">
|
|
{{ __('(use 256 x 256 size for better view)') }}
|
|
<div class="field_img mt-2">
|
|
<img src="{{ empty($custom_field->image) ? asset('assets/img_placeholder.jpeg') : $custom_field->image }}"
|
|
alt="" id="blah"
|
|
class="preview-image img w-25">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-6 form-group mandatory">
|
|
<div class="form-check form-switch ">
|
|
<input type="hidden" name="required" id="required"
|
|
value="{{ $custom_field->required ? '1' : '0' }}">
|
|
<input class="form-check-input status-switch" type="checkbox"
|
|
role="switch" aria-label="required"
|
|
{{ $custom_field->required ? 'checked' : '' }}>{{ __('Required') }}
|
|
<label class="form-check-label" for="required"></label>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6 form-group mandatory">
|
|
<div class="form-check form-switch ">
|
|
<input type="hidden" name="status" id="status"
|
|
value="{{ $custom_field->status ? '1' : '0' }}">
|
|
<input class="form-check-input status-switch" type="checkbox"
|
|
role="switch" aria-label="status"
|
|
{{ $custom_field->status ? 'checked' : '' }}>{{ __('Active') }}
|
|
<label class="form-check-label" for="status"></label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
<div class="form-group">
|
|
<label>{{ __('Field Values') }} ({{ $lang->name }})</label>
|
|
{{-- <select name="values[{{ $lang->id }}][]" data-tags="true"
|
|
data-placeholder="{{ __('Select an option') }}" data-allow-clear="true"
|
|
data-token-separators="[',']" class="select2 w-100 full-width-select2"
|
|
multiple="multiple" @if ($lang->id == 1) @endif>
|
|
@php
|
|
$fieldValues = [];
|
|
if ($lang->id == 1) {
|
|
$fieldValues = is_array($custom_field->values)
|
|
? $custom_field->values
|
|
: [];
|
|
} elseif (
|
|
isset($translations[$lang->id]['value']) &&
|
|
is_array($translations[$lang->id]['value'])
|
|
) {
|
|
$fieldValues = $translations[$lang->id]['value'];
|
|
}
|
|
@endphp
|
|
@foreach ($fieldValues as $value)
|
|
<option value="{{ $value }}" selected>{{ $value }}
|
|
</option>
|
|
@endforeach
|
|
</select> --}}
|
|
@php
|
|
$fieldValues = [];
|
|
|
|
if ($lang->id == 1) {
|
|
$fieldValues = is_array($custom_field->values)
|
|
? $custom_field->values
|
|
: [];
|
|
} elseif (
|
|
isset($translations[$lang->id]['value']) &&
|
|
is_array($translations[$lang->id]['value'])
|
|
) {
|
|
$fieldValues = $translations[$lang->id]['value'];
|
|
}
|
|
|
|
if (is_string($fieldValues)) {
|
|
$fieldValues = json_decode($fieldValues, true);
|
|
}
|
|
|
|
if (!is_array($fieldValues)) {
|
|
$fieldValues = [];
|
|
}
|
|
|
|
// Ensure all values including 0 are preserved as strings for Tagify
|
|
$fieldValues = array_map(function($v) {
|
|
return $v !== null && $v !== '' ? (string)$v : '';
|
|
}, $fieldValues);
|
|
@endphp
|
|
|
|
|
|
<input
|
|
type="text"
|
|
name="values[{{ $lang->id }}]"
|
|
class="tagify-input w-100"
|
|
value='@json($fieldValues ?? [])'
|
|
data-field-values='@json($fieldValues ?? [])'
|
|
>
|
|
|
|
|
|
|
|
@if ($lang->id != 1)
|
|
<small
|
|
class="text-muted">{{ __('Used for translatable field types.') }}</small>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-6 col-sm-12">
|
|
<div class="card">
|
|
<div class="card-header">{{ __('Category') }}</div>
|
|
<div class="card-body mt-2">
|
|
<div class="sub_category_lit">
|
|
@foreach ($categories as $category)
|
|
<div class="category">
|
|
<div class="category-header">
|
|
<label>
|
|
<input type="checkbox" name="selected_categories[]"
|
|
value="{{ $category->id }}"
|
|
{{ in_array($category->id, $selected_categories) ? 'checked' : '' }}>
|
|
{{ $category->name }}
|
|
</label>
|
|
@if (!empty($category->subcategories))
|
|
@php
|
|
// Get current language from Session (not from foreach loop)
|
|
$currentLang = Session::get('language');
|
|
// Check RTL: use accessor which returns boolean (rtl != 0)
|
|
$isRtl = false;
|
|
if (!empty($currentLang)) {
|
|
try {
|
|
// Try to get raw attribute first, fallback to accessor
|
|
$rtlRaw = method_exists($currentLang, 'getRawOriginal') ? $currentLang->getRawOriginal('rtl') : null;
|
|
if ($rtlRaw !== null) {
|
|
$isRtl = ($rtlRaw == 1 || $rtlRaw === true);
|
|
} else {
|
|
$isRtl = ($currentLang->rtl == true || $currentLang->rtl === 1);
|
|
}
|
|
} catch (\Exception $e) {
|
|
$isRtl = ($currentLang->rtl == true || $currentLang->rtl === 1);
|
|
}
|
|
}
|
|
$arrowIcon = $isRtl ? '' : ''; // fa-caret-left for RTL, fa-caret-right for LTR
|
|
@endphp
|
|
<i style="font-size:24px"
|
|
class="fas toggle-button {{ in_array($category->id, $selected_all_categories) ? 'open' : '' }}">
|
|
{!! $arrowIcon !!}
|
|
</i>
|
|
@endif
|
|
</div>
|
|
|
|
{{-- ✅ Show children open if parent or child is selected --}}
|
|
<div class="subcategories"
|
|
style="display: {{ in_array($category->id, $selected_all_categories) ? 'block' : 'none' }};">
|
|
@if (!empty($category->subcategories))
|
|
@include('category.treeview', [
|
|
'categories' => $category->subcategories,
|
|
'selected_categories' => $selected_categories,
|
|
'selected_all_categories' => $selected_all_categories,
|
|
])
|
|
@endif
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-12 text-end mb-3">
|
|
<input type="submit" class="btn btn-primary" value="{{ __('Save and Back') }}">
|
|
</div>
|
|
</div>
|
|
</form>
|
|
<!-- @if (in_array($custom_field->type, ['radio', 'checkbox', 'dropdown']))
|
|
<div class="col-md-12 col-sm-12">
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<table class="table table-borderless table-striped" id="table_list"
|
|
data-toggle="table" data-url="{{ route('custom-fields.value.show', $custom_field->id) }}"
|
|
data-click-to-select="true"
|
|
data-page-list="[5, 10, 20, 50, 100, 200]" data-search="true" data-search-align="right"
|
|
data-toolbar="#toolbar" data-show-columns="true" data-show-refresh="true"
|
|
data-trim-on-search="false" data-responsive="true" data-sort-name="id"
|
|
data-escape="true"
|
|
data-sort-order="desc" data-query-params="queryParams"
|
|
data-table="custom_fields" data-use-row-attr-func="true" data-mobile-responsive="true">
|
|
<thead class="thead-dark">
|
|
<tr>
|
|
<th scope="col" data-field="id" data-align="center" data-sortable="true">{{ __('ID') }}</th>
|
|
<th scope="col" data-field="value" data-align="center" data-sortable="true">{{ __('Value') }}</th>
|
|
<th scope="col" data-field="operate"data-escape="false" data-align="center" data-sortable="false" data-events="customFieldValueEvents">{{ __('Action') }}</th>
|
|
</tr>
|
|
</thead>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endif -->
|
|
{{-- add modal --}}
|
|
@if (in_array($custom_field->type, ['radio', 'checkbox', 'dropdown']))
|
|
<div id="addModal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel1"
|
|
aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="myModalLabel1">{{ __('Add Values') }}</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"
|
|
aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form action="{{ route('custom-fields.value.add', $custom_field->id) }}"
|
|
class="create-form form-horizontal" enctype="multipart/form-data" method="POST"
|
|
data-parsley-validate>
|
|
@csrf
|
|
<div class="col-md-12 form-group mandatory">
|
|
<label for="values" class="mandatory form-label">{{ __('Field Values') }}</label>
|
|
<input type="text" name="values" id="values" class="form-control"
|
|
value="{{ old('values') }}" data-parsley-required="true">
|
|
</div>
|
|
|
|
<input type="hidden" name="field_id" id="field_id" value="{{ $custom_field->id }}">
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary waves-effect"
|
|
data-bs-dismiss="modal">{{ __('Close') }}</button>
|
|
<button type="submit"
|
|
class="btn btn-primary waves-effect waves-light">{{ __('Save') }}</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- /.modal-content -->
|
|
</div>
|
|
{{-- edit modal --}}
|
|
<div id="editModal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel1"
|
|
aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="myModalLabel1">{{ __('Edit Custome Field Values') }}</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"
|
|
aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form action="{{ route('custom-fields.value.update', $custom_field->id) }}"
|
|
class="edit-form form-horizontal" enctype="multipart/form-data" method="POST"
|
|
data-parsley-validate>
|
|
@csrf
|
|
<input type="hidden" name="old_custom_field_value" id="old_custom_field_value" />
|
|
<div class="col-md-12 form-group mandatory">
|
|
<label for="new_custom_field_value"
|
|
class="mandatory form-label">{{ __('Name') }}</label>
|
|
<input type="text" name="new_custom_field_value" id="new_custom_field_value"
|
|
class="form-control" value="" data-parsley-required="true">
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary waves-effect"
|
|
data-bs-dismiss="modal">{{ __('Close') }}</button>
|
|
<button type="submit"
|
|
class="btn btn-primary waves-effect waves-light">{{ __('Save') }}</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- /.modal-content -->
|
|
@endif
|
|
</div>
|
|
</section>
|
|
@endsection
|
|
@section('js')
|
|
<script>
|
|
window.existingTranslations = @json($translations ?? []);
|
|
// console.log('Loaded Translations:', window.existingTranslations);
|
|
</script>
|
|
|
|
<script>
|
|
function updateCustomFieldUI() {
|
|
const type = $('select[name="type"]').val();
|
|
const valuesTypes = ['radio', 'dropdown', 'checkbox'];
|
|
|
|
$('.tab-pane').each(function() {
|
|
const $tab = $(this);
|
|
|
|
const $fieldValues = $tab.find('select[name^="values"]')
|
|
.closest('.form-group');
|
|
|
|
const $minMaxGroup = $tab.find('.min-max-fields');
|
|
|
|
if (valuesTypes.includes(type)) {
|
|
$fieldValues.show();
|
|
$minMaxGroup.hide();
|
|
} else if (type === 'fileinput') {
|
|
$fieldValues.hide();
|
|
$minMaxGroup.hide();
|
|
} else {
|
|
$fieldValues.hide();
|
|
$minMaxGroup.show();
|
|
}
|
|
});
|
|
}
|
|
|
|
$(document).ready(function() {
|
|
updateCustomFieldUI();
|
|
|
|
$(document).on('change', 'select[name="type"]', function() {
|
|
updateCustomFieldUI();
|
|
});
|
|
|
|
// Initialize select2 for all value selects
|
|
$('select[name^="values"]').each(function() {
|
|
if (!$(this).hasClass('select2-hidden-accessible')) {
|
|
$(this).select2({
|
|
tags: true,
|
|
tokenSeparators: [','],
|
|
placeholder: "{{ __('Select an option') }}",
|
|
allowClear: true
|
|
});
|
|
}
|
|
});
|
|
|
|
// Image preview functionality
|
|
$('#image').on('change', function() {
|
|
const [file] = this.files;
|
|
if (file) {
|
|
$('#blah').attr('src', URL.createObjectURL(file));
|
|
}
|
|
});
|
|
});
|
|
|
|
function afterCustomFieldUpdate() {
|
|
setTimeout(function() {
|
|
window.location.href = "{{ route('custom-fields.index') }}"
|
|
}, 1000)
|
|
}
|
|
|
|
// document.addEventListener('DOMContentLoaded', function () {
|
|
|
|
// const input = document.querySelector('.tagify-input');
|
|
|
|
// new Tagify(input, {
|
|
// delimiters: ",",
|
|
// editTags: true,
|
|
// duplicate: false,
|
|
// dropdown: {
|
|
// enabled: 0
|
|
// }
|
|
// });
|
|
// });
|
|
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
document.querySelectorAll('.tagify-input').forEach((input) => {
|
|
if (!input.tagify) {
|
|
// Get initial values from data attribute or value attribute
|
|
let initialValues = [];
|
|
try {
|
|
const dataValues = input.getAttribute('data-field-values');
|
|
if (dataValues) {
|
|
initialValues = JSON.parse(dataValues);
|
|
} else if (input.value) {
|
|
initialValues = JSON.parse(input.value);
|
|
}
|
|
} catch (e) {
|
|
console.warn('Error parsing initial values:', e);
|
|
}
|
|
|
|
// Ensure all values including 0 are converted to strings
|
|
initialValues = initialValues.map(v => {
|
|
// Preserve 0, false, empty string, etc. as strings
|
|
return v !== null && v !== undefined ? String(v) : '';
|
|
}).filter(v => v !== ''); // Only filter out truly empty strings
|
|
|
|
// Initialize Tagify with proper configuration
|
|
const tagify = new Tagify(input, {
|
|
delimiters: ",",
|
|
editTags: true,
|
|
duplicate: false,
|
|
dropdown: {
|
|
enabled: 0
|
|
},
|
|
// Ensure 0 and other falsy values are preserved
|
|
transformTag: function(tagData) {
|
|
// Convert tag value to string to preserve 0
|
|
if (tagData.value !== null && tagData.value !== undefined) {
|
|
tagData.value = String(tagData.value);
|
|
}
|
|
return tagData;
|
|
},
|
|
// Ensure all values including 0 are kept
|
|
whitelist: [],
|
|
enforceWhitelist: false,
|
|
// Don't trim values to preserve spaces if needed
|
|
trim: false
|
|
});
|
|
|
|
// Set initial values after initialization
|
|
if (initialValues.length > 0) {
|
|
tagify.addTags(initialValues);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
|
|
</script>
|
|
@endsection
|