1. 修正客戶管理頁面 H1 標題與麵包屑導覽路徑。 2. 在機台編輯頁面實作分頁功能(基本、營運、機台系統設定)。 3. 實作極簡奢華風的機台系統設定 UI,按功能模組(電子發票、刷卡、支付、購物車等)進行卡片式分組。 4. 將系統設定資料從 Company JSON 遷移至 Machine 資料表獨立欄位,並更新關聯控制器與模型邏輯。 5. 清理 CompanyController 與視圖中的冗餘設定邏輯。 6. 完成現有資料遷移,確保機台正確繼承客戶層級之設定。 7. 優化倉儲管理「現有庫存」矩陣視圖與導覽功能。
609 lines
51 KiB
PHP
609 lines
51 KiB
PHP
@extends('layouts.admin')
|
|
|
|
@section('content')
|
|
<div class="space-y-2 pb-20">
|
|
|
|
|
|
<!-- Header Section -->
|
|
<div class="flex flex-col md:flex-row md:items-center justify-between gap-4 mb-8">
|
|
<div class="flex items-center gap-4">
|
|
<a href="{{ route('admin.basic-settings.machines.index') }}"
|
|
class="inline-flex items-center justify-center w-10 h-10 rounded-xl bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 text-slate-500 hover:text-cyan-500 hover:border-cyan-500/20 transition-all shadow-sm group">
|
|
<svg class="w-5 h-5 stroke-[2.5]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18"/>
|
|
</svg>
|
|
</a>
|
|
<div>
|
|
<h1 class="text-2xl font-black text-slate-800 dark:text-white tracking-tight items-center flex gap-3 outfit-font">
|
|
{{ __('Edit Machine') }}
|
|
</h1>
|
|
<p class="text-xs font-bold text-slate-500 dark:text-slate-400 mt-1.5 flex items-center gap-2 uppercase tracking-widest leading-none">
|
|
<span class="inline-flex items-center px-2 py-1 rounded-lg bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-300 border border-slate-200 dark:border-slate-800 font-mono tracking-tighter">
|
|
{{ $machine->name }} / {{ $machine->serial_no }}
|
|
</span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center gap-3">
|
|
<button type="submit" form="edit-form" class="btn-luxury-primary flex items-center gap-2">
|
|
<svg class="w-4 h-4 stroke-[2.5]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" />
|
|
</svg>
|
|
<span>{{ __('Save Changes') }}</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<form id="edit-form" x-data="{
|
|
imagePreviews: [
|
|
{{ isset($machine->images[0]) ? "'" . Storage::disk('public')->url($machine->images[0]) . "'" : 'null' }},
|
|
{{ isset($machine->images[1]) ? "'" . Storage::disk('public')->url($machine->images[1]) . "'" : 'null' }},
|
|
{{ isset($machine->images[2]) ? "'" . Storage::disk('public')->url($machine->images[2]) . "'" : 'null' }}
|
|
],
|
|
removeImages: [false, false, false],
|
|
handleImageUpload(event, index) {
|
|
const file = event.target.files[0];
|
|
if (!file) return;
|
|
const reader = new FileReader();
|
|
reader.onload = (e) => {
|
|
this.imagePreviews[index] = e.target.result;
|
|
this.removeImages[index] = false;
|
|
};
|
|
reader.readAsDataURL(file);
|
|
},
|
|
removeImage(index) {
|
|
this.imagePreviews[index] = null;
|
|
this.removeImages[index] = true;
|
|
if (this.$refs['imageInput_' + index]) this.$refs['imageInput_' + index].value = '';
|
|
},
|
|
submitForm() {
|
|
if (!this.$el.name.value.trim()) {
|
|
window.dispatchEvent(new CustomEvent('toast', {
|
|
detail: { message: '{{ __("Enter machine name") }}', type: 'error' }
|
|
}));
|
|
return;
|
|
}
|
|
if (!this.$el.serial_no.value.trim()) {
|
|
window.dispatchEvent(new CustomEvent('toast', {
|
|
detail: { message: '{{ __("Enter serial number") }}', type: 'error' }
|
|
}));
|
|
return;
|
|
}
|
|
if (!this.$el.machine_model_id.value.trim()) {
|
|
window.dispatchEvent(new CustomEvent('toast', {
|
|
detail: { message: '{{ __("Please select a machine model") }}', type: 'error' }
|
|
}));
|
|
return;
|
|
}
|
|
this.$el.submit();
|
|
}
|
|
}" @submit.prevent="submitForm" action="{{ route('admin.basic-settings.machines.update', $machine) }}" method="POST" enctype="multipart/form-data"
|
|
x-data="{ activeTab: 'basic' }" class="space-y-6">
|
|
@csrf
|
|
@method('PUT')
|
|
|
|
<!-- Validation Errors -->
|
|
@if ($errors->any())
|
|
<div class="luxury-card p-6 bg-rose-500/5 border-rose-500/10 mb-8 animate-luxury-in">
|
|
<div class="flex items-center gap-3 mb-4 text-rose-500">
|
|
<svg class="w-5 h-5 stroke-[2.5]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z"/>
|
|
</svg>
|
|
<h4 class="font-black text-sm tracking-tight capitalize">{{ __('Some fields need attention') }}</h4>
|
|
</div>
|
|
<ul class="space-y-2">
|
|
@foreach ($errors->all() as $error)
|
|
<li class="text-xs font-bold text-rose-500/80 flex items-center gap-2">
|
|
<span class="w-1 h-1 rounded-full bg-rose-500/40"></span>
|
|
{{ $error }}
|
|
</li>
|
|
@endforeach
|
|
</ul>
|
|
</div>
|
|
@endif
|
|
|
|
<!-- Tab Headers -->
|
|
<div class="flex items-center gap-1 p-1 bg-slate-100 dark:bg-slate-800/50 rounded-2xl w-fit mb-4">
|
|
<button type="button" @click="activeTab = 'basic'"
|
|
:class="activeTab === 'basic' ? 'bg-white dark:bg-slate-800 text-cyan-500 shadow-sm' : 'text-slate-500 hover:text-slate-700 dark:hover:text-slate-300'"
|
|
class="px-6 py-2.5 rounded-xl text-sm font-black uppercase tracking-widest transition-all duration-300 flex items-center gap-2">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
|
|
{{ __('Basic Information') }}
|
|
</button>
|
|
<button type="button" @click="activeTab = 'operation'"
|
|
:class="activeTab === 'operation' ? 'bg-white dark:bg-slate-800 text-amber-500 shadow-sm' : 'text-slate-500 hover:text-slate-700 dark:hover:text-slate-300'"
|
|
class="px-6 py-2.5 rounded-xl text-sm font-black uppercase tracking-widest transition-all duration-300 flex items-center gap-2">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/></svg>
|
|
{{ __('Operational Parameters') }}
|
|
</button>
|
|
<button type="button" @click="activeTab = 'system'"
|
|
:class="activeTab === 'system' ? 'bg-white dark:bg-slate-800 text-indigo-500 shadow-sm' : 'text-slate-500 hover:text-slate-700 dark:hover:text-slate-300'"
|
|
class="px-6 py-2.5 rounded-xl text-sm font-black uppercase tracking-widest transition-all duration-300 flex items-center gap-2">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/></svg>
|
|
{{ __('Machine System Settings') }}
|
|
</button>
|
|
</div>
|
|
|
|
<div class="flex flex-col lg:flex-row gap-8 items-start">
|
|
<!-- Main Content Area -->
|
|
<div class="flex-1 space-y-8 order-2 lg:order-1 capitalize">
|
|
|
|
<!-- Tab: Basic Information -->
|
|
<div x-show="activeTab === 'basic'" x-transition:enter="transition ease-out duration-300" x-transition:enter-start="opacity-0 translate-y-4" x-transition:enter-end="opacity-100 translate-y-0" class="space-y-6">
|
|
<!-- Left: Basic info & Hardware -->
|
|
<div class="lg:col-span-2 space-y-6">
|
|
<!-- Basic Information -->
|
|
<div class="luxury-card rounded-3xl p-7 animate-luxury-in relative z-20">
|
|
<div class="flex items-center gap-3 mb-8">
|
|
<div class="w-10 h-10 rounded-xl bg-emerald-500/10 flex items-center justify-center text-emerald-500">
|
|
<svg class="w-5 h-5 stroke-[2.5]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15 9h3.75M15 12h3.75M15 15h3.75M4.5 19.5h15a2.25 2.25 0 0 0 2.25-2.25V6.75A2.25 2.25 0 0 0 18.75 4.5H5.25a2.25 2.25 0 0 0-2.25 2.25v10.5A2.25 2.25 0 0 0 4.5 19.5Zm6-10.125a1.875 1.875 0 1 1-3.75 0 1.875 1.875 0 0 1 3.75 0Zm1.294 6.336a6.721 6.721 0 0 1-3.17.789 6.721 6.721 0 0 1-3.168-.789 3.376 3.376 0 0 1 6.338 0Z"/>
|
|
</svg>
|
|
</div>
|
|
<h3 class="text-lg font-black text-slate-800 dark:text-white tracking-tight">{{ __('Basic Information') }}</h3>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-x-8 gap-y-6">
|
|
<div>
|
|
<label class="block text-xs font-bold text-slate-400 uppercase tracking-[0.15em] mb-2">{{ __('Machine Name') }} <span class="text-rose-500">*</span></label>
|
|
<input type="text" name="name" value="{{ old('name', $machine->name) }}" class="luxury-input w-full">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-bold text-slate-400 uppercase tracking-[0.15em] mb-2">{{ __('Machine Serial No') }} <span class="text-rose-500">*</span></label>
|
|
<input type="text" name="serial_no" value="{{ old('serial_no', $machine->serial_no) }}" class="luxury-input w-full">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-bold text-slate-400 uppercase tracking-[0.15em] mb-2">{{ __('Location') }}</label>
|
|
<input type="text" name="location" value="{{ old('location', $machine->location) }}" class="luxury-input w-full" placeholder="{{ __('e.g., Taipei Station') }}">
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-xs font-bold text-slate-400 uppercase tracking-[0.15em] mb-2">{{ __('Machine Model') }} <span class="text-rose-500">*</span></label>
|
|
<x-searchable-select
|
|
name="machine_model_id"
|
|
:selected="old('machine_model_id', $machine->machine_model_id)"
|
|
>
|
|
@foreach($models as $model)
|
|
<option value="{{ $model->id }}" {{ old('machine_model_id', $machine->machine_model_id) == $model->id ? 'selected' : '' }}>{{ $model->name }}</option>
|
|
@endforeach
|
|
</x-searchable-select>
|
|
</div>
|
|
@if(auth()->user()->isSystemAdmin())
|
|
<div>
|
|
<label class="block text-xs font-bold text-slate-400 uppercase tracking-[0.15em] mb-2">{{ __('Company') }}</label>
|
|
<x-searchable-select
|
|
name="company_id"
|
|
:selected="old('company_id', $machine->company_id)"
|
|
:placeholder="__('No Company')"
|
|
>
|
|
@foreach($companies as $company)
|
|
<option value="{{ $company->id }}" {{ old('company_id', $machine->company_id) == $company->id ? 'selected' : '' }}
|
|
data-title="{{ $company->name }}{{ $company->code ? ' (' . $company->code . ')' : '' }}">
|
|
{{ $company->name }}{{ $company->code ? ' (' . $company->code . ')' : '' }}
|
|
</option>
|
|
@endforeach
|
|
</x-searchable-select>
|
|
@error('company_id') <p class="mt-1 text-xs text-rose-500 font-bold uppercase tracking-wider">{{ $message }}</p> @enderror
|
|
</div>
|
|
@endif
|
|
|
|
<div x-data="machineGeocoding()" class="col-span-full grid grid-cols-1 md:grid-cols-4 gap-6 pt-6 border-t border-slate-100 dark:border-slate-800">
|
|
<div class="md:col-span-2">
|
|
<label class="block text-xs font-bold text-slate-400 uppercase tracking-[0.15em] mb-2">{{ __('Address') }}</label>
|
|
<div class="flex gap-2">
|
|
<input type="text" name="address" x-model="address" class="luxury-input w-full" placeholder="{{ __('Enter full address') }}">
|
|
<button type="button" @click="geocode()" :disabled="loading" class="btn-luxury-ghost py-2 px-3 flex items-center gap-2 whitespace-nowrap min-w-[120px] justify-center">
|
|
<template x-if="!loading">
|
|
<div class="flex items-center gap-2">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"/></svg>
|
|
<span>{{ __('Resolve Coordinates') }}</span>
|
|
</div>
|
|
</template>
|
|
<template x-if="loading">
|
|
<div class="flex items-center gap-2">
|
|
<svg class="animate-spin h-4 w-4 text-indigo-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>
|
|
<span>{{ __('Searching...') }}</span>
|
|
</div>
|
|
</template>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-bold text-slate-400 uppercase tracking-[0.15em] mb-2">{{ __('Latitude') }}</label>
|
|
<input type="number" step="any" name="latitude" value="{{ old('latitude', $machine->latitude) }}" class="luxury-input w-full" placeholder="{{ __('e.g., 25.0330') }}">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-bold text-slate-400 uppercase tracking-[0.15em] mb-2">{{ __('Longitude') }}</label>
|
|
<input type="number" step="any" name="longitude" value="{{ old('longitude', $machine->longitude) }}" class="luxury-input w-full" placeholder="{{ __('e.g., 121.5654') }}">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tab: Operational Parameters -->
|
|
<div x-show="activeTab === 'operation'" x-transition:enter="transition ease-out duration-300" x-transition:enter-start="opacity-0 translate-y-4" x-transition:enter-end="opacity-100 translate-y-0" class="space-y-6">
|
|
<!-- Operational Parameters -->
|
|
<div class="luxury-card rounded-3xl p-8 animate-luxury-in relative z-10">
|
|
<div class="flex items-center gap-3 mb-8">
|
|
<div class="w-10 h-10 rounded-xl bg-amber-500/10 flex items-center justify-center text-amber-500">
|
|
<svg class="w-5 h-5 stroke-[2.5]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 6h9.75M10.5 6a1.5 1.5 0 1 1-3 0m3 0a1.5 1.5 0 1 0-3 0M3.75 6H7.5m3 12h9.75m-9.75 0a1.5 1.5 0 1 1-3 0m3 0a1.5 1.5 0 1 0-3 0m-3.75 0H7.5m9-6h3.75m-3.75 0a1.5 1.5 0 1 1-3 0m3 0a1.5 1.5 0 1 0-3 0M3.75 12h7.5"/>
|
|
</svg>
|
|
</div>
|
|
<h3 class="text-lg font-black text-slate-800 dark:text-white tracking-tight">{{ __('Operational Parameters') }}</h3>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-x-8 gap-y-6">
|
|
<div>
|
|
<label class="block text-xs font-bold text-slate-400 uppercase tracking-[0.15em] mb-2">{{ __('Card Reader Seconds') }}</label>
|
|
<input type="number" name="card_reader_seconds" value="{{ $machine->card_reader_seconds }}" class="luxury-input w-full">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-bold text-slate-400 uppercase tracking-[0.15em] mb-2">{{ __('Payment Buffer Seconds') }}</label>
|
|
<input type="number" name="payment_buffer_seconds" value="{{ $machine->payment_buffer_seconds }}" class="luxury-input w-full">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-bold text-slate-400 uppercase tracking-[0.15em] mb-2">{{ __('Checkout Time 1') }}</label>
|
|
<x-luxury-time-input name="card_reader_checkout_time_1" value="{{ $machine->card_reader_checkout_time_1 }}" />
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-bold text-slate-400 uppercase tracking-[0.15em] mb-2">{{ __('Checkout Time 2') }}</label>
|
|
<x-luxury-time-input name="card_reader_checkout_time_2" value="{{ $machine->card_reader_checkout_time_2 }}" />
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-bold text-slate-400 uppercase tracking-[0.15em] mb-2">{{ __('Heating Start Time') }}</label>
|
|
<x-luxury-time-input name="heating_start_time" value="{{ $machine->heating_start_time }}" />
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-bold text-slate-400 uppercase tracking-[0.15em] mb-2">{{ __('Heating End Time') }}</label>
|
|
<x-luxury-time-input name="heating_end_time" value="{{ $machine->heating_end_time }}" />
|
|
</div>
|
|
<div class="col-span-full">
|
|
<label class="block text-xs font-bold text-slate-400 uppercase tracking-[0.15em] mb-2">{{ __('Payment Config') }}</label>
|
|
<x-searchable-select
|
|
name="payment_config_id"
|
|
:selected="old('payment_config_id', $machine->payment_config_id)"
|
|
:placeholder="__('Not Used')"
|
|
:hasSearch="false"
|
|
>
|
|
@foreach($paymentConfigs as $config)
|
|
<option value="{{ $config->id }}" {{ $machine->payment_config_id == $config->id ? 'selected' : '' }}>{{ $config->name }}</option>
|
|
@endforeach
|
|
</x-searchable-select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- hardware & slot types -->
|
|
<div class="luxury-card rounded-3xl p-7 animate-luxury-in">
|
|
<div class="flex items-center gap-3 mb-8">
|
|
<div class="w-10 h-10 rounded-xl bg-amber-500/10 flex items-center justify-center text-amber-500">
|
|
<svg class="w-5 h-5 stroke-[2.5]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M21 7.5V18a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 18V7.5m0-4.5h18M3 7.5h18M3 12h18M3 16.5h18"/>
|
|
</svg>
|
|
</div>
|
|
<h3 class="text-lg font-black text-slate-800 dark:text-white tracking-tight">{{ __('Hardware & Slots') }}</h3>
|
|
</div>
|
|
|
|
<div class="space-y-8">
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-x-8 gap-y-6">
|
|
<div>
|
|
<label class="block text-xs font-bold text-slate-400 uppercase tracking-[0.15em] mb-2">{{ __('Card Reader No') }}</label>
|
|
<input type="text" name="card_reader_no" value="{{ $machine->card_reader_no }}" class="luxury-input w-full">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-bold text-slate-400 uppercase tracking-[0.15em] mb-2">{{ __('Key No') }}</label>
|
|
<input type="text" name="key_no" value="{{ $machine->key_no }}" class="luxury-input w-full">
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-xs font-bold text-slate-400 uppercase tracking-[0.15em] mb-4">{{ __('Slot Mechanism (default: Conveyor, check for Spring)') }}</label>
|
|
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-6 gap-4">
|
|
@foreach([['1-10', 'is_spring_slot_1_10'], ['11-20', 'is_spring_slot_11_20'], ['21-30', 'is_spring_slot_21_30'], ['31-40', 'is_spring_slot_31_40'], ['41-50', 'is_spring_slot_41_50'], ['51-60', 'is_spring_slot_51_60']] as $slot)
|
|
<label class="flex items-center gap-3 p-3 rounded-xl border border-slate-100 dark:border-slate-800 bg-slate-50/50 dark:bg-slate-900/50 cursor-pointer hover:border-amber-500/30 transition-all">
|
|
<input type="hidden" name="{{ $slot[1] }}" value="0">
|
|
<input type="checkbox" name="{{ $slot[1] }}" value="1" {{ $machine->{$slot[1]} ? 'checked' : '' }} class="w-4 h-4 rounded text-amber-500 focus:ring-amber-500/20">
|
|
<span class="text-xs font-bold text-slate-600 dark:text-slate-400">{{ $slot[0] }}</span>
|
|
</label>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tab: Machine System Settings -->
|
|
<div x-show="activeTab === 'system'" x-transition:enter="transition ease-out duration-300" x-transition:enter-start="opacity-0 translate-y-4" x-transition:enter-end="opacity-100 translate-y-0" class="space-y-6">
|
|
<div class="luxury-card rounded-3xl p-8 animate-luxury-in relative z-10">
|
|
<div class="flex items-center gap-3 mb-8">
|
|
<div class="w-10 h-10 rounded-xl bg-indigo-500/10 flex items-center justify-center text-indigo-500">
|
|
<svg class="w-5 h-5 stroke-[2.5]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/>
|
|
</svg>
|
|
</div>
|
|
<h3 class="text-lg font-black text-slate-800 dark:text-white tracking-tight">{{ __('Machine System Settings') }}</h3>
|
|
</div>
|
|
|
|
<div class="space-y-4">
|
|
<!-- Electronic Invoice Section -->
|
|
<div class="p-6 rounded-2xl bg-slate-50/50 dark:bg-slate-900/50 border border-slate-100 dark:border-slate-800 space-y-6">
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex items-center gap-3">
|
|
<div class="p-2 rounded-lg bg-emerald-500/10 text-emerald-500">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" /></svg>
|
|
</div>
|
|
<div>
|
|
<span class="block text-sm font-black text-slate-700 dark:text-slate-200">{{ __('Electronic Invoice') }}</span>
|
|
<span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">{{ __('System-wide Invoice Support') }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="relative inline-flex items-center cursor-pointer">
|
|
<input type="hidden" name="tax_invoice_enabled" value="0">
|
|
<input type="checkbox" name="tax_invoice_enabled" value="1" {{ $machine->tax_invoice_enabled ? 'checked' : '' }} class="sr-only peer">
|
|
<div class="w-11 h-6 bg-slate-200 dark:bg-slate-700 rounded-full peer peer-focus:ring-4 peer-focus:ring-emerald-500/20 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-emerald-500 transition-colors"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="pt-4 border-t border-slate-100 dark:border-slate-800">
|
|
<label class="block text-xs font-bold text-slate-400 uppercase tracking-[0.15em] mb-2">{{ __('Invoice Status') }}</label>
|
|
<x-searchable-select
|
|
name="invoice_status"
|
|
:selected="old('invoice_status', $machine->invoice_status)"
|
|
:hasSearch="false"
|
|
>
|
|
<option value="0" {{ $machine->invoice_status == 0 ? 'selected' : '' }}>{{ __('No Invoice') }}</option>
|
|
<option value="1" {{ $machine->invoice_status == 1 ? 'selected' : '' }}>{{ __('Default Donate') }}</option>
|
|
<option value="2" {{ $machine->invoice_status == 2 ? 'selected' : '' }}>{{ __('Default Not Donate') }}</option>
|
|
</x-searchable-select>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Card System -->
|
|
<label class="flex items-center justify-between p-6 rounded-2xl bg-slate-50/50 dark:bg-slate-900/50 border border-slate-100 dark:border-slate-800 cursor-pointer group hover:border-blue-500/30 transition-all">
|
|
<div class="flex items-center gap-3">
|
|
<div class="p-2 rounded-lg bg-blue-500/10 text-blue-500">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" /></svg>
|
|
</div>
|
|
<div>
|
|
<span class="block text-sm font-black text-slate-700 dark:text-slate-200 group-hover:text-blue-500 transition-colors">{{ __('Card System') }}</span>
|
|
<span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">{{ __('Includes Credit Card/Mobile Pay') }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="relative inline-flex items-center">
|
|
<input type="hidden" name="card_terminal_enabled" value="0">
|
|
<input type="checkbox" name="card_terminal_enabled" value="1" {{ $machine->card_terminal_enabled ? 'checked' : '' }} class="sr-only peer">
|
|
<div class="w-11 h-6 bg-slate-200 dark:bg-slate-700 rounded-full peer peer-focus:ring-4 peer-focus:ring-blue-500/20 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-500 transition-colors"></div>
|
|
</div>
|
|
</label>
|
|
|
|
<!-- E.SUN QR Pay -->
|
|
<label class="flex items-center justify-between p-6 rounded-2xl bg-slate-50/50 dark:bg-slate-900/50 border border-slate-100 dark:border-slate-800 cursor-pointer group hover:border-emerald-500/30 transition-all">
|
|
<div class="flex items-center gap-3">
|
|
<div class="p-2 rounded-lg bg-emerald-500/10 text-emerald-500">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M12 4v1m6 11h2m-6 0h-2v4m0-11v3m0 0h.01M12 12h4.01M16 20h4M4 12h4m12 0h.01M5 8h2a1 1 0 001-1V5a1 1 0 00-1-1H5a1 1 0 00-1 1v2a1 1 0 001 1zm12 0h2a1 1 0 001-1V5a1 1 0 00-1-1h-2a1 1 0 00-1 1v2a1 1 0 001 1zM5 17h2a1 1 0 001-1v-2a1 1 0 00-1-1H5a1 1 0 00-1 1v2a1 1 0 001 1z" /></svg>
|
|
</div>
|
|
<div>
|
|
<span class="block text-sm font-black text-slate-700 dark:text-slate-200 group-hover:text-emerald-500 transition-colors">{{ __('E.SUN QR Pay') }}</span>
|
|
<span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">{{ __('Scan to Pay via E.SUN') }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="relative inline-flex items-center">
|
|
<input type="hidden" name="scan_pay_esun_enabled" value="0">
|
|
<input type="checkbox" name="scan_pay_esun_enabled" value="1" {{ $machine->scan_pay_esun_enabled ? 'checked' : '' }} class="sr-only peer">
|
|
<div class="w-11 h-6 bg-slate-200 dark:bg-slate-700 rounded-full peer peer-focus:ring-4 peer-focus:ring-emerald-500/20 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-emerald-500 transition-colors"></div>
|
|
</div>
|
|
</label>
|
|
|
|
<!-- LinePay -->
|
|
<label class="flex items-center justify-between p-6 rounded-2xl bg-slate-50/50 dark:bg-slate-900/50 border border-slate-100 dark:border-slate-800 cursor-pointer group hover:border-green-500/30 transition-all">
|
|
<div class="flex items-center gap-3">
|
|
<div class="p-2 rounded-lg bg-green-500/10 text-green-500">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M17 9V7a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2m2 4h10a2 2 0 002-2v-6a2 2 0 00-2-2H9a2 2 0 00-2 2v6a2 2 0 002 2zm7-5a2 2 0 11-4 0 2 2 0 014 0z" /></svg>
|
|
</div>
|
|
<div>
|
|
<span class="block text-sm font-black text-slate-700 dark:text-slate-200 group-hover:text-green-500 transition-colors">{{ __('LinePay Payment') }}</span>
|
|
<span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">{{ __('Mobile Payment Support') }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="relative inline-flex items-center">
|
|
<input type="hidden" name="scan_pay_linepay_enabled" value="0">
|
|
<input type="checkbox" name="scan_pay_linepay_enabled" value="1" {{ $machine->scan_pay_linepay_enabled ? 'checked' : '' }} class="sr-only peer">
|
|
<div class="w-11 h-6 bg-slate-200 dark:bg-slate-700 rounded-full peer peer-focus:ring-4 peer-focus:ring-green-500/20 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-green-500 transition-colors"></div>
|
|
</div>
|
|
</label>
|
|
|
|
<!-- Shopping Cart -->
|
|
<label class="flex items-center justify-between p-6 rounded-2xl bg-slate-50/50 dark:bg-slate-900/50 border border-slate-100 dark:border-slate-800 cursor-pointer group hover:border-purple-500/30 transition-all">
|
|
<div class="flex items-center gap-3">
|
|
<div class="p-2 rounded-lg bg-purple-500/10 text-purple-500">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z" /></svg>
|
|
</div>
|
|
<div>
|
|
<span class="block text-sm font-black text-slate-700 dark:text-slate-200 group-hover:text-purple-500 transition-colors">{{ __('Shopping Cart Feature') }}</span>
|
|
<span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">{{ __('Batch Purchasing Support') }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="relative inline-flex items-center">
|
|
<input type="hidden" name="shopping_cart_enabled" value="0">
|
|
<input type="checkbox" name="shopping_cart_enabled" value="1" {{ $machine->shopping_cart_enabled ? 'checked' : '' }} class="sr-only peer">
|
|
<div class="w-11 h-6 bg-slate-200 dark:bg-slate-700 rounded-full peer peer-focus:ring-4 peer-focus:ring-purple-500/20 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-purple-500 transition-colors"></div>
|
|
</div>
|
|
</label>
|
|
|
|
<!-- Welcome Gift -->
|
|
<label class="flex items-center justify-between p-6 rounded-2xl bg-slate-50/50 dark:bg-slate-900/50 border border-slate-100 dark:border-slate-800 cursor-pointer group hover:border-rose-500/30 transition-all">
|
|
<div class="flex items-center gap-3">
|
|
<div class="p-2 rounded-lg bg-rose-500/10 text-rose-500">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-14v4m0 0l8 4m-8-4l-8 4m8 4v10l8-4m0-14l-8 4" /></svg>
|
|
</div>
|
|
<div>
|
|
<span class="block text-sm font-black text-slate-700 dark:text-slate-200 group-hover:text-rose-500 transition-colors">{{ __('Welcome Gift Feature') }}</span>
|
|
<span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">{{ __('Promotion & Gifting') }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="relative inline-flex items-center">
|
|
<input type="hidden" name="welcome_gift_enabled" value="0">
|
|
<input type="checkbox" name="welcome_gift_enabled" value="1" {{ $machine->welcome_gift_enabled ? 'checked' : '' }} class="sr-only peer">
|
|
<div class="w-11 h-6 bg-slate-200 dark:bg-slate-700 rounded-full peer peer-focus:ring-4 peer-focus:ring-rose-500/20 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-rose-500 transition-colors"></div>
|
|
</div>
|
|
</label>
|
|
|
|
<!-- Cash Module -->
|
|
<label class="flex items-center justify-between p-6 rounded-2xl bg-slate-50/50 dark:bg-slate-900/50 border border-slate-100 dark:border-slate-800 cursor-pointer group hover:border-amber-500/30 transition-all">
|
|
<div class="flex items-center gap-3">
|
|
<div class="p-2 rounded-lg bg-amber-500/10 text-amber-500">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M17 9V7a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2m2 4h10a2 2 0 002-2v-6a2 2 0 00-2-2H9a2 2 0 00-2 2v6a2 2 0 002 2zm7-5a2 2 0 11-4 0 2 2 0 014 0z" /></svg>
|
|
</div>
|
|
<div>
|
|
<span class="block text-sm font-black text-slate-700 dark:text-slate-200 group-hover:text-amber-500 transition-colors">{{ __('Cash Module Feature') }}</span>
|
|
<span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">{{ __('Coin/Bill Acceptor Support') }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="relative inline-flex items-center">
|
|
<input type="hidden" name="cash_module_enabled" value="0">
|
|
<input type="checkbox" name="cash_module_enabled" value="1" {{ $machine->cash_module_enabled ? 'checked' : '' }} class="sr-only peer">
|
|
<div class="w-11 h-6 bg-slate-200 dark:bg-slate-700 rounded-full peer peer-focus:ring-4 peer-focus:ring-amber-500/20 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-amber-500 transition-colors"></div>
|
|
</div>
|
|
</label>
|
|
|
|
<!-- Member System -->
|
|
<label class="flex items-center justify-between p-6 rounded-2xl bg-slate-50/50 dark:bg-slate-900/50 border border-slate-100 dark:border-slate-800 cursor-pointer group hover:border-indigo-500/30 transition-all">
|
|
<div class="flex items-center gap-3">
|
|
<div class="p-2 rounded-lg bg-indigo-500/10 text-indigo-500">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z"/></svg>
|
|
</div>
|
|
<div>
|
|
<span class="block text-sm font-black text-slate-700 dark:text-slate-200 group-hover:text-indigo-500 transition-colors">{{ __('Member System') }}</span>
|
|
<span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">{{ __('Member Login & Points Support') }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="relative inline-flex items-center">
|
|
<input type="hidden" name="member_system_enabled" value="0">
|
|
<input type="checkbox" name="member_system_enabled" value="1" {{ $machine->member_system_enabled ? 'checked' : '' }} class="sr-only peer">
|
|
<div class="w-11 h-6 bg-slate-200 dark:bg-slate-700 rounded-full peer peer-focus:ring-4 peer-focus:ring-indigo-500/20 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-indigo-500 transition-colors"></div>
|
|
</div>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Sidebar Content -->
|
|
<div class="w-full lg:w-96 space-y-8 order-1 lg:order-2 lg:sticky top-24">
|
|
<!-- Machine Images -->
|
|
<div class="luxury-card rounded-[2.5rem] p-8 animate-luxury-in">
|
|
<div class="flex items-center gap-3 mb-8">
|
|
<div class="w-10 h-10 rounded-xl bg-cyan-500/10 flex items-center justify-center text-cyan-500">
|
|
<svg class="w-5 h-5 stroke-[2.5]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="m2.25 15.75 5.159-5.159a2.25 2.25 0 0 1 3.182 0l5.159 5.159m-1.5-1.5 1.409-1.409a2.25 2.25 0 0 1 3.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 0 0 1.5-1.5V6a1.5 1.5 0 0 0-1.5-1.5H3.75A1.5 1.5 0 0 0 2.25 6v12a1.5 1.5 0 0 0 1.5 1.5Zm10.5-11.25h.008v.008h-.008V8.25Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z" />
|
|
</svg>
|
|
</div>
|
|
<h3 class="text-lg font-black text-slate-800 dark:text-white tracking-tight">{{ __('Machine Images') }}</h3>
|
|
</div>
|
|
|
|
<div class="space-y-8">
|
|
@for($i = 0; $i < 3; $i++)
|
|
<div class="space-y-3">
|
|
<div class="flex items-center justify-between px-1 text-xs font-black text-slate-400 uppercase tracking-widest">
|
|
<span>{{ __('Photo Slot') }} {{ $i + 1 }}</span>
|
|
<template x-if="imagePreviews[{{ $i }}]">
|
|
<span class="text-emerald-500 flex items-center gap-1 lowercase tracking-normal font-bold">
|
|
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="m4.5 12.75 6 6 9-13.5"/></svg>
|
|
{{ __('set') }}
|
|
</span>
|
|
</template>
|
|
</div>
|
|
|
|
<div class="relative group">
|
|
<input type="hidden" name="remove_image_{{ $i }}" :value="removeImages[{{ $i }}] ? '1' : '0'">
|
|
|
|
<template x-if="!imagePreviews[{{ $i }}]">
|
|
<div @click="$refs.imageInput_{{ $i }}.click()" class="aspect-video rounded-2xl border-2 border-dashed border-slate-200 dark:border-slate-800 bg-slate-50/50 dark:bg-slate-900/50 flex flex-col items-center justify-center gap-3 cursor-pointer hover:bg-slate-100 dark:hover:bg-slate-800/80 hover:border-cyan-500/50 transition-all duration-300 group/upload">
|
|
<div class="p-2.5 rounded-xl bg-white dark:bg-slate-800 shadow-sm border border-slate-100 dark:border-slate-700 group-hover/upload:scale-110 group-hover/upload:text-cyan-500 transition-all duration-300 text-slate-400">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15"/></svg>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-[10px] font-black text-slate-500 dark:text-slate-400 uppercase tracking-tighter">{{ __('Click to upload') }}</p>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<template x-if="imagePreviews[{{ $i }}]">
|
|
<div class="relative aspect-video rounded-2xl overflow-hidden border border-slate-200 dark:border-slate-800 shadow-lg group/image">
|
|
<img :src="imagePreviews[{{ $i }}]" class="w-full h-full object-cover">
|
|
<div class="absolute inset-0 bg-slate-950/40 opacity-0 group-hover/image:opacity-100 transition-opacity duration-300 flex items-center justify-center gap-3">
|
|
<button type="button" @click="$refs.imageInput_{{ $i }}.click()" class="p-2.5 rounded-xl bg-white text-slate-800 hover:bg-cyan-500 hover:text-white transition-all duration-300 shadow-lg">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="3"><path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99" /></svg>
|
|
</button>
|
|
<button type="button" @click="removeImage({{ $i }})" class="p-2.5 rounded-xl bg-white text-slate-800 hover:bg-rose-500 hover:text-white transition-all duration-300 shadow-lg">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="3"><path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.244 2.244 0 0 1-2.244 2.077H8.084a2.244 2.244 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" /></svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<input type="file" name="image_{{ $i }}" x-ref="imageInput_{{ $i }}" class="hidden" accept="image/*" @change="handleImageUpload($event, {{ $i }})">
|
|
</div>
|
|
</div>
|
|
@endfor
|
|
|
|
<div class="p-4 rounded-2xl bg-slate-50 dark:bg-slate-900/50 border border-slate-100 dark:border-white/5">
|
|
<p class="text-[10px] font-bold text-slate-400 leading-relaxed uppercase tracking-widest text-center">
|
|
{{ __('PNG, JPG, WEBP up to 10MB') }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
@endsection
|
|
|
|
@section('scripts')
|
|
<script>
|
|
function machineGeocoding() {
|
|
return {
|
|
address: @js($machine->address ?? ''),
|
|
loading: false,
|
|
async geocode() {
|
|
if (!this.address) {
|
|
window.dispatchEvent(new CustomEvent('toast', { detail: { message: @js(__('Please enter address first')), type: 'error' } }));
|
|
return;
|
|
}
|
|
this.loading = true;
|
|
try {
|
|
const response = await fetch(@js(route('admin.basic-settings.machines.geocode')), {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
|
|
'Accept': 'application/json',
|
|
},
|
|
body: JSON.stringify({ address: this.address })
|
|
});
|
|
const data = await response.json();
|
|
if (data.success) {
|
|
document.querySelector('input[name=latitude]').value = parseFloat(data.lat).toFixed(6);
|
|
document.querySelector('input[name=longitude]').value = parseFloat(data.lon).toFixed(6);
|
|
window.dispatchEvent(new CustomEvent('toast', { detail: { message: @js(__('Location found!')), type: 'success' } }));
|
|
} else {
|
|
window.dispatchEvent(new CustomEvent('toast', { detail: { message: @js(__('Location not found')), type: 'error' } }));
|
|
}
|
|
} catch (error) {
|
|
console.error('Geocoding error:', error);
|
|
window.dispatchEvent(new CustomEvent('toast', { detail: { message: @js(__('Error searching location')), type: 'error' } }));
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
@endsection
|
|
|