275 lines
14 KiB
PHP
Executable File
275 lines
14 KiB
PHP
Executable File
<?php
|
|
|
|
use App\Models\App;
|
|
use App\Models\User;
|
|
use App\Models\Tasks;
|
|
|
|
$users = User::get();
|
|
$apps = App::get();
|
|
|
|
if (isset($task)) {
|
|
$selectedAssignees = [];
|
|
if ($task && $task->assignees) {
|
|
$decoded = json_decode($task->assignees, true);
|
|
$selectedAssignees = is_array($decoded) ? $decoded : [];
|
|
}
|
|
}
|
|
|
|
|
|
?>
|
|
@extends('app')
|
|
@section('content')
|
|
<div class="w-full mt-[70px] justify-center container flex">
|
|
<div class="ui-card">
|
|
<div class="ui-card-header">{{isset($task) ? "ویرایش وظیفه" : "ایجاد وظیفه جدید"}}</div>
|
|
<form action="{{isset($task) ? Route('task.edit') : Route('task.create')}}" method="POST" class="ui-card-body ui-form-stack">
|
|
@csrf
|
|
@if(isset($task))
|
|
<input type="hidden" id="id" name="id" value="{{$task->id}}">
|
|
@endif
|
|
|
|
<div class="ui-form-field">
|
|
<label for="title"><span class="text-red-500">*</span> عنوان</label>
|
|
<input class="ui-input" value="{{$task->title ?? null}}" type="text"
|
|
id="title" name="title" required>
|
|
</div>
|
|
|
|
<div class="ui-form-field">
|
|
<label for="description">توضیحات</label>
|
|
<textarea id="description" name="description" class="ui-input">{{$task->description ?? null}}</textarea>
|
|
</div>
|
|
|
|
<div class="ui-form-field">
|
|
<label for="priority">اولویت</label>
|
|
<select id="priority" name="priority" class="ui-input">
|
|
<option value="none" {{ old('priority', $task->priority ?? '') == 'none' ? 'selected' : '' }}>ندارد</option>
|
|
<option value="low" {{ old('priority', $task->priority ?? '') == 'low' ? 'selected' : '' }}>کم</option>
|
|
<option value="medium" {{ old('priority', $task->priority ?? '') == 'medium' ? 'selected' : '' }}>عادی</option>
|
|
<option value="urgent" {{ old('priority', $task->priority ?? '') == 'urgent' ? 'selected' : '' }}>فوری</option>
|
|
<option value="high" {{ old('priority', $task->priority ?? '') == 'high' ? 'selected' : '' }}>زیاد</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="ui-form-field">
|
|
<label for="start_date">تاریخ شروع <span class="text-red-500">*</span></label>
|
|
<input type="text" id="start_date" name="start_date_display" class="ui-input"
|
|
value="{{$task->start_date ?? null}}"
|
|
placeholder="تاریخ شروع" autocomplete="off" readonly required>
|
|
<input type="hidden" name="start_date" id="start_date_gregorian">
|
|
</div>
|
|
|
|
<div class="ui-form-field">
|
|
<label for="target_date">تاریخ هدف</label>
|
|
<div class="ui-input-wrap">
|
|
<input type="text" id="target_date" name="target_date_display" class="ui-input"
|
|
value="{{$task->target_date ?? null}}"
|
|
placeholder="تاریخ هدف" autocomplete="off" readonly>
|
|
<button type="button" id="clear_target_date" class="ui-input-clear" aria-label="پاک کردن تاریخ هدف">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
|
d="M6 18L18 6M6 6l12 12"></path>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
<input type="hidden" name="target_date" id="target_date_gregorian">
|
|
</div>
|
|
|
|
<div class="ui-form-field">
|
|
<label for="state"><span class="text-red-500">*</span> وضعیت</label>
|
|
<select id="state" name="state" class="ui-input" required>
|
|
<option value="1" {{ old('state', $task->state ?? '') == 1 ? 'selected' : '' }}>در انتظار</option>
|
|
<option value="2" {{ old('state', $task->state ?? '') == 2 ? 'selected' : '' }}>در صف انجام</option>
|
|
<option value="3" {{ old('state', $task->state ?? '') == 3 ? 'selected' : '' }}>درحال انجام</option>
|
|
<option value="4" {{ old('state', $task->state ?? '') == 4 ? 'selected' : '' }}>انجامشده</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="ui-form-field ui-form-field--dropdown">
|
|
<label for="dropdown-btn">انتصاب کاربران</label>
|
|
<div id="dropdown-container">
|
|
<button type="button" id="dropdown-btn"
|
|
class="ui-input text-right flex justify-between items-center w-full">
|
|
<span id="selected-count">انتخاب کاربران</span>
|
|
<svg class="w-4 h-4 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
|
d="M19 9l-7 7-7-7"></path>
|
|
</svg>
|
|
</button>
|
|
|
|
<div id="dropdown-list"
|
|
class="hidden ui-form-dropdown-panel">
|
|
|
|
<div class="p-2 border-b">
|
|
<input type="text" id="search-input"
|
|
class="w-full px-3 py-1 border border-gray-200 rounded-lg text-sm"
|
|
placeholder="جستجوی کاربر...">
|
|
</div>
|
|
|
|
<div id="users-list" class="max-h-48 overflow-y-auto space-y-1 p-1">
|
|
@foreach($users as $user)
|
|
<label class="user-item flex items-center gap-2 p-1 hover:bg-gray-50 rounded cursor-pointer"
|
|
data-name="{{ $user->name }}">
|
|
<input type="checkbox"
|
|
name="assignees[]"
|
|
value="{{ $user->id }}"
|
|
class="user-checkbox rounded text-cyan-600"
|
|
{{ isset($task) && (in_array($user->id, $selectedAssignees)) ? 'checked' : '' }}>
|
|
|
|
<span>{{ $user->name }}</span>
|
|
</label>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="ui-form-field">
|
|
<label for="app">نام اپ</label>
|
|
<select id="app" name="app" class="ui-input">
|
|
<option value="">-- انتخاب اپ --</option>
|
|
@if(!empty($apps) && count($apps) > 0)
|
|
@foreach($apps as $app)
|
|
<option value="{{ $app->id }}" {{ old('app', $task->app ?? '') == $app->id ? 'selected' : '' }}>
|
|
{{ $app->name_fa }} {{ $app->type_fa }}
|
|
</option>
|
|
@endforeach
|
|
@endif
|
|
</select>
|
|
</div>
|
|
|
|
<div class="ui-form-actions">
|
|
<button type="submit"
|
|
class="bg-cyan-600 text-white py-2 px-6 rounded-lg hover:bg-cyan-700 transition">
|
|
{{isset($task) ? "ویرایش" : "ایجاد وظیفه جدید"}}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
const dropdownBtn = document.getElementById('dropdown-btn');
|
|
const dropdownList = document.getElementById('dropdown-list');
|
|
const dropdownField = document.querySelector('.ui-form-field--dropdown');
|
|
const searchInput = document.getElementById('search-input');
|
|
const usersList = document.getElementById('users-list');
|
|
const selectedCountSpan = document.getElementById('selected-count');
|
|
|
|
function setAssigneeDropdownOpen(open) {
|
|
dropdownList.classList.toggle('hidden', !open);
|
|
if (dropdownField) {
|
|
dropdownField.classList.toggle('is-open', open);
|
|
}
|
|
}
|
|
|
|
dropdownBtn.addEventListener('click', (e) => {
|
|
e.stopPropagation();
|
|
const willOpen = dropdownList.classList.contains('hidden');
|
|
setAssigneeDropdownOpen(willOpen);
|
|
if (willOpen) {
|
|
searchInput.focus();
|
|
}
|
|
});
|
|
|
|
document.addEventListener('click', (e) => {
|
|
if (!dropdownBtn.contains(e.target) && !dropdownList.contains(e.target)) {
|
|
setAssigneeDropdownOpen(false);
|
|
}
|
|
});
|
|
|
|
searchInput.addEventListener('input', function () {
|
|
const searchText = this.value.toLowerCase();
|
|
const items = usersList.querySelectorAll('.user-item');
|
|
|
|
items.forEach(item => {
|
|
const name = item.getAttribute('data-name').toLowerCase();
|
|
item.style.display = name.includes(searchText) ? 'flex' : 'none';
|
|
});
|
|
});
|
|
|
|
function updateSelectedCount() {
|
|
const selected = document.querySelectorAll('.user-checkbox:checked');
|
|
const count = selected.length;
|
|
selectedCountSpan.textContent = count === 0 ? 'انتخاب کاربران' : count + ' کاربر انتخاب شده';
|
|
}
|
|
|
|
document.querySelectorAll('.user-checkbox').forEach(checkbox => {
|
|
checkbox.addEventListener('change', updateSelectedCount);
|
|
});
|
|
|
|
updateSelectedCount();
|
|
|
|
$(document).ready(function () {
|
|
function syncGregorianFromDisplay(displaySelector, hiddenSelector) {
|
|
const displayVal = $(displaySelector).val();
|
|
if (!displayVal || $(hiddenSelector).val()) return;
|
|
try {
|
|
// اگر مقدار نمایشی شمسی YYYY/MM/DD باشد
|
|
const parts = String(displayVal).replace(/-/g, '/').split('/');
|
|
if (parts.length === 3) {
|
|
const pDate = new persianDate([Number(parts[0]), Number(parts[1]), Number(parts[2])]);
|
|
const gregorian = pDate.toCalendar('gregorian').toLocale('en').format('YYYY-MM-DD');
|
|
$(hiddenSelector).val(gregorian);
|
|
}
|
|
} catch (e) {
|
|
}
|
|
}
|
|
|
|
$('#start_date').persianDatepicker({
|
|
format: 'YYYY/MM/DD',
|
|
autoClose: true,
|
|
toolbox: {
|
|
calendarSwitch: {enabled: false},
|
|
todayButton: {enabled: true, text: {fa: 'امروز'}}
|
|
},
|
|
onSelect: function (unix) {
|
|
let gregorian = new persianDate(unix).toCalendar('gregorian').toLocale('en');
|
|
let dateStr = gregorian.format('YYYY-MM-DD');
|
|
$('#start_date_gregorian').val(dateStr);
|
|
}
|
|
});
|
|
|
|
$('#target_date').persianDatepicker({
|
|
format: 'YYYY/MM/DD',
|
|
autoClose: true,
|
|
toolbox: {
|
|
calendarSwitch: {enabled: false},
|
|
todayButton: {enabled: true, text: {fa: 'امروز'}}
|
|
},
|
|
onSelect: function (unix) {
|
|
let gregorianDate = new persianDate(unix).toCalendar('gregorian').toLocale('en');
|
|
let dateStrTarget = gregorianDate.format('YYYY-MM-DD');
|
|
$('#target_date_gregorian').val(dateStrTarget);
|
|
}
|
|
});
|
|
|
|
// اگر مقدار اولیه از دیتابیس آمده، فیلد مخفی میلادی را هم پر کن
|
|
@if(!empty($task?->start_date))
|
|
$('#start_date_gregorian').val(@json(\Carbon\Carbon::parse($task->start_date)->format('Y-m-d')));
|
|
$('#start_date').val(@json(\Morilog\Jalali\Jalalian::fromCarbon(\Carbon\Carbon::parse($task->start_date))->format('Y/m/d')));
|
|
@endif
|
|
@if(!empty($task?->target_date))
|
|
$('#target_date_gregorian').val(@json(\Carbon\Carbon::parse($task->target_date)->format('Y-m-d')));
|
|
$('#target_date').val(@json(\Morilog\Jalali\Jalalian::fromCarbon(\Carbon\Carbon::parse($task->target_date))->format('Y/m/d')));
|
|
@endif
|
|
|
|
$('form').on('submit', function (e) {
|
|
syncGregorianFromDisplay('#start_date', '#start_date_gregorian');
|
|
syncGregorianFromDisplay('#target_date', '#target_date_gregorian');
|
|
if (!$('#start_date_gregorian').val()) {
|
|
e.preventDefault();
|
|
alert('لطفاً تاریخ شروع را از تقویم انتخاب کنید.');
|
|
return false;
|
|
}
|
|
});
|
|
|
|
$('#clear_target_date').on('click', function () {
|
|
$('#target_date').val('');
|
|
$('#target_date_gregorian').val('');
|
|
});
|
|
});
|
|
</script>
|
|
|
|
@endsection
|