- Increased icon sizes in service items, service orders, users, and technician management for better visibility. - Added custom loading indicators with appropriate icons in search fields for vehicles, work orders, and technicians. - Introduced invoice management routes for better organization and access control. - Created a new test for the estimate PDF functionality to ensure proper rendering and data integrity.
317 lines
18 KiB
PHP
317 lines
18 KiB
PHP
<div class="p-6">
|
|
<!-- Header -->
|
|
<div class="flex items-center justify-between mb-6">
|
|
<div>
|
|
<h1 class="text-2xl font-semibold text-zinc-900 dark:text-white">Create New User</h1>
|
|
<p class="text-zinc-600 dark:text-zinc-400">Add a new user to the system</p>
|
|
</div>
|
|
<a href="{{ route('users.index') }}"
|
|
class="inline-flex items-center px-4 py-2 text-zinc-700 dark:text-zinc-300 bg-zinc-100 dark:bg-zinc-700 text-sm font-medium rounded-md hover:bg-zinc-200 dark:hover:bg-zinc-600 transition-colors"
|
|
wire:navigate>
|
|
<svg class="w-6 h-6 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"></path>
|
|
</svg>
|
|
Back to Users
|
|
</a>
|
|
</div>
|
|
|
|
<form wire:submit="save" class="space-y-6">
|
|
<!-- Personal Information -->
|
|
<div class="bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg p-6">
|
|
<h3 class="text-lg font-medium text-zinc-900 dark:text-white mb-4">Personal Information</h3>
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">
|
|
Full Name *
|
|
</label>
|
|
<input type="text"
|
|
wire:model="form.name"
|
|
class="w-full rounded-md border-zinc-300 dark:border-zinc-600 dark:bg-zinc-700 dark:text-white shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
|
@error('form.name') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">
|
|
Email Address *
|
|
</label>
|
|
<input type="email"
|
|
wire:model="form.email"
|
|
class="w-full rounded-md border-zinc-300 dark:border-zinc-600 dark:bg-zinc-700 dark:text-white shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
|
@error('form.email') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">
|
|
Phone Number
|
|
</label>
|
|
<input type="text"
|
|
wire:model="form.phone"
|
|
class="w-full rounded-md border-zinc-300 dark:border-zinc-600 dark:bg-zinc-700 dark:text-white shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
|
@error('form.phone') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">
|
|
National ID
|
|
</label>
|
|
<input type="text"
|
|
wire:model="form.national_id"
|
|
class="w-full rounded-md border-zinc-300 dark:border-zinc-600 dark:bg-zinc-700 dark:text-white shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
|
@error('form.national_id') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
|
|
</div>
|
|
|
|
<div class="md:col-span-2">
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">
|
|
Address
|
|
</label>
|
|
<textarea wire:model="form.address"
|
|
rows="3"
|
|
class="w-full rounded-md border-zinc-300 dark:border-zinc-600 dark:bg-zinc-700 dark:text-white shadow-sm focus:border-blue-500 focus:ring-blue-500"></textarea>
|
|
@error('form.address') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Professional Information -->
|
|
<div class="bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg p-6">
|
|
<h3 class="text-lg font-medium text-zinc-900 dark:text-white mb-4">Professional Information</h3>
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">
|
|
Position
|
|
</label>
|
|
<input type="text"
|
|
wire:model="form.position"
|
|
class="w-full rounded-md border-zinc-300 dark:border-zinc-600 dark:bg-zinc-700 dark:text-white shadow-sm focus:border-blue-500 focus:ring-blue-500"
|
|
list="position-suggestions">
|
|
<datalist id="position-suggestions">
|
|
@foreach($positions as $suggestion)
|
|
<option value="{{ $suggestion }}">
|
|
@endforeach
|
|
</datalist>
|
|
@error('form.position') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">
|
|
Department
|
|
</label>
|
|
<select wire:model="form.department"
|
|
wire:change="updatePositionSuggestions"
|
|
class="w-full rounded-md border-zinc-300 dark:border-zinc-600 dark:bg-zinc-700 dark:text-white shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
|
<option value="">Select Department</option>
|
|
<option value="management">Management</option>
|
|
<option value="service">Service Department</option>
|
|
<option value="parts">Parts Department</option>
|
|
<option value="body_shop">Body Shop</option>
|
|
<option value="sales">Sales</option>
|
|
<option value="administration">Administration</option>
|
|
<option value="customer_service">Customer Service</option>
|
|
</select>
|
|
@error('form.department') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">
|
|
Salary
|
|
</label>
|
|
<input type="number"
|
|
step="0.01"
|
|
wire:model="form.salary"
|
|
class="w-full rounded-md border-zinc-300 dark:border-zinc-600 dark:bg-zinc-700 dark:text-white shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
|
@error('form.salary') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">
|
|
Hire Date
|
|
</label>
|
|
<input type="date"
|
|
wire:model="form.hire_date"
|
|
class="w-full rounded-md border-zinc-300 dark:border-zinc-600 dark:bg-zinc-700 dark:text-white shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
|
@error('form.hire_date') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
|
|
</div>
|
|
|
|
<div class="md:col-span-2">
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">
|
|
Emergency Contact
|
|
</label>
|
|
<input type="text"
|
|
wire:model="form.emergency_contact"
|
|
placeholder="Name, relationship, phone number"
|
|
class="w-full rounded-md border-zinc-300 dark:border-zinc-600 dark:bg-zinc-700 dark:text-white shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
|
@error('form.emergency_contact') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Account Settings -->
|
|
<div class="bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg p-6">
|
|
<h3 class="text-lg font-medium text-zinc-900 dark:text-white mb-4">Account Settings</h3>
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">
|
|
Account Status
|
|
</label>
|
|
<select wire:model="form.status"
|
|
class="w-full rounded-md border-zinc-300 dark:border-zinc-600 dark:bg-zinc-700 dark:text-white shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
|
<option value="active">Active</option>
|
|
<option value="inactive">Inactive</option>
|
|
<option value="suspended">Suspended</option>
|
|
</select>
|
|
@error('form.status') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">
|
|
Branch
|
|
</label>
|
|
<select wire:model="branch_code"
|
|
class="w-full rounded-md border-zinc-300 dark:border-zinc-600 dark:bg-zinc-700 dark:text-white shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
|
<option value="">Select Branch</option>
|
|
@foreach($branches as $branch)
|
|
<option value="{{ $branch->code }}">{{ $branch->name }} ({{ $branch->code }})</option>
|
|
@endforeach
|
|
</select>
|
|
@error('branch_code') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Role Assignment -->
|
|
<div class="bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg p-6">
|
|
<h3 class="text-lg font-medium text-zinc-900 dark:text-white mb-4">Role Assignment</h3>
|
|
|
|
<!-- Quick Role Presets -->
|
|
<div class="mb-4">
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">
|
|
Quick Presets
|
|
</label>
|
|
<div class="flex flex-wrap gap-2">
|
|
<button type="button"
|
|
wire:click="applyRolePreset('manager')"
|
|
class="px-3 py-1 text-xs font-medium text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/20 rounded-md hover:bg-blue-100 dark:hover:bg-blue-900/30 transition-colors">
|
|
Manager
|
|
</button>
|
|
<button type="button"
|
|
wire:click="applyRolePreset('technician')"
|
|
class="px-3 py-1 text-xs font-medium text-green-600 dark:text-green-400 bg-green-50 dark:bg-green-900/20 rounded-md hover:bg-green-100 dark:hover:bg-green-900/30 transition-colors">
|
|
Technician
|
|
</button>
|
|
<button type="button"
|
|
wire:click="applyRolePreset('receptionist')"
|
|
class="px-3 py-1 text-xs font-medium text-purple-600 dark:text-purple-400 bg-purple-50 dark:bg-purple-900/20 rounded-md hover:bg-purple-100 dark:hover:bg-purple-900/30 transition-colors">
|
|
Receptionist
|
|
</button>
|
|
<button type="button"
|
|
wire:click="applyRolePreset('parts_clerk')"
|
|
class="px-3 py-1 text-xs font-medium text-amber-600 dark:text-amber-400 bg-amber-50 dark:bg-amber-900/20 rounded-md hover:bg-amber-100 dark:hover:bg-amber-900/30 transition-colors">
|
|
Parts Clerk
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Role Selection -->
|
|
<div class="space-y-3">
|
|
@foreach($roles as $role)
|
|
<label class="flex items-center">
|
|
<input type="checkbox"
|
|
wire:model="form.roles"
|
|
value="{{ $role->id }}"
|
|
class="rounded border-zinc-300 dark:border-zinc-600 text-blue-600 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
|
<div class="ml-3">
|
|
<span class="text-sm font-medium text-zinc-900 dark:text-white">{{ $role->display_name }}</span>
|
|
@if($role->description)
|
|
<p class="text-xs text-zinc-500 dark:text-zinc-400">{{ $role->description }}</p>
|
|
@endif
|
|
</div>
|
|
</label>
|
|
@endforeach
|
|
</div>
|
|
@error('form.roles') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
|
|
</div>
|
|
|
|
<!-- Password -->
|
|
<div class="bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg p-6">
|
|
<h3 class="text-lg font-medium text-zinc-900 dark:text-white mb-4">Password</h3>
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">
|
|
Password *
|
|
</label>
|
|
<input type="password"
|
|
wire:model="form.password"
|
|
class="w-full rounded-md border-zinc-300 dark:border-zinc-600 dark:bg-zinc-700 dark:text-white shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
|
@error('form.password') <span class="text-red-500 text-sm">{{ $message }}</span> @enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">
|
|
Confirm Password *
|
|
</label>
|
|
<input type="password"
|
|
wire:model="form.password_confirmation"
|
|
class="w-full rounded-md border-zinc-300 dark:border-zinc-600 dark:bg-zinc-700 dark:text-white shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-4">
|
|
<button type="button"
|
|
wire:click="generatePassword"
|
|
class="px-4 py-2 text-sm font-medium text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/20 rounded-md hover:bg-blue-100 dark:hover:bg-blue-900/30 transition-colors">
|
|
Generate Random Password
|
|
</button>
|
|
|
|
@if($generatedPassword)
|
|
<div class="mt-2 p-3 bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-md">
|
|
<p class="text-sm text-yellow-800 dark:text-yellow-200">
|
|
<strong>Generated Password:</strong>
|
|
<code class="font-mono bg-yellow-100 dark:bg-yellow-900/40 px-1 py-0.5 rounded">{{ $generatedPassword }}</code>
|
|
</p>
|
|
<p class="text-xs text-yellow-600 dark:text-yellow-300 mt-1">
|
|
Make sure to share this password securely with the user.
|
|
</p>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Notification Settings -->
|
|
<div class="bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg p-6">
|
|
<h3 class="text-lg font-medium text-zinc-900 dark:text-white mb-4">Notification Settings</h3>
|
|
<div class="space-y-3">
|
|
<label class="flex items-center">
|
|
<input type="checkbox"
|
|
wire:model="form.send_welcome_email"
|
|
class="rounded border-zinc-300 dark:border-zinc-600 text-blue-600 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
|
<span class="ml-3 text-sm text-zinc-900 dark:text-white">Send welcome email to user</span>
|
|
</label>
|
|
|
|
<label class="flex items-center">
|
|
<input type="checkbox"
|
|
wire:model="form.force_password_reset"
|
|
class="rounded border-zinc-300 dark:border-zinc-600 text-blue-600 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
|
<span class="ml-3 text-sm text-zinc-900 dark:text-white">Force password reset on first login</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Action Buttons -->
|
|
<div class="flex items-center justify-end pt-6 border-t border-zinc-200 dark:border-zinc-700">
|
|
<div class="flex gap-3">
|
|
<a href="{{ route('users.index') }}"
|
|
class="px-6 py-2 text-sm font-medium text-zinc-700 dark:text-zinc-300 bg-zinc-100 dark:bg-zinc-700 rounded-md hover:bg-zinc-200 dark:hover:bg-zinc-600 transition-colors">
|
|
Cancel
|
|
</a>
|
|
|
|
<button type="submit"
|
|
class="px-6 py-2 bg-blue-600 text-white text-sm font-medium rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed"
|
|
wire:loading.attr="disabled">
|
|
<span wire:loading.remove>Create User</span>
|
|
<span wire:loading>Creating...</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|