name ?? 'نامشخص'; $titleBefore = (string)($before['title'] ?? ''); $titleAfter = (string)($after['title'] ?? $task->title ?? ''); $lines[] = "ویرایش تسک: «{$titleAfter}»"; $lines[] = "توسط: {$actorName}"; $appBefore = $before['app'] ?? null; $appAfter = $after['app'] ?? $task->app ?? null; $a1 = App::find($appBefore)?->name_fa ?? ($appBefore ?? '-'); $a2 = App::find($appAfter)?->name_fa ?? ($appAfter ?? '-'); $lines[] = ($appBefore != $appAfter) ? "اپ: {$a1} ← {$a2}" : "اپ: {$a2}"; $lines[] = (($before['title'] ?? null) !== ($after['title'] ?? null)) ? "عنوان: {$titleBefore} ← {$titleAfter}" : "عنوان: {$titleAfter}"; $priorityFa = [ 'none' => 'ندارد', 'low' => 'کم', 'medium' => 'عادی', 'high' => 'زیاد', 'urgent' => 'فوری', ]; $p1 = $before['priority'] ?? null; $p2 = $after['priority'] ?? null; $lines[] = ($p1 !== $p2) ? "اولویت: " . ($priorityFa[$p1] ?? ($p1 ?? '-')) . " ← " . ($priorityFa[$p2] ?? ($p2 ?? '-')) : "اولویت: " . ($priorityFa[$p2] ?? ($p2 ?? '-')); $stateFa = [ 1 => 'انباشته', 2 => 'برای انجام', 3 => 'درحال انجام', 4 => 'پایان یافته', ]; $s1 = (int)($before['state'] ?? 0); $s2 = (int)($after['state'] ?? 0); $lines[] = ($s1 !== $s2 && $s2) ? "وضعیت: " . ($stateFa[$s1] ?? ($before['state'] ?? '-')) . " ← " . ($stateFa[$s2] ?? ($after['state'] ?? '-')) : "وضعیت: " . ($stateFa[$s2] ?? ($after['state'] ?? '-')); $d1 = $before['start_date'] ?? null; $d2 = $after['start_date'] ?? null; $lines[] = ($d1 !== $d2) ? "شروع: " . ($d1 ?: '-') . " ← " . ($d2 ?: '-') : "شروع: " . ($d2 ?: '-'); $t1 = $before['target_date'] ?? null; $t2 = $after['target_date'] ?? null; $lines[] = ($t1 !== $t2) ? "ددلاین: " . ($t1 ?: '-') . " ← " . ($t2 ?: '-') : "ددلاین: " . ($t2 ?: '-'); $desc1 = trim((string)($before['description'] ?? '')); $desc2 = trim((string)($after['description'] ?? '')); $lines[] = ($desc1 !== $desc2) ? "توضیحات: " . (!empty($desc2) ? 'تغییر کرد' : 'پاک شد') : "توضیحات: بدون تغییر"; $aBefore = $before['assignees'] ?? null; $aAfter = $after['assignees'] ?? null; $arr1 = is_string($aBefore) ? json_decode($aBefore, true) : $aBefore; $arr2 = is_string($aAfter) ? json_decode($aAfter, true) : $aAfter; $arr1 = is_array($arr1) ? array_map('strval', $arr1) : []; $arr2 = is_array($arr2) ? array_map('strval', $arr2) : []; sort($arr1); sort($arr2); $names1 = User::whereIn('id', $arr1)->pluck('name')->all(); $names2 = User::whereIn('id', $arr2)->pluck('name')->all(); $lines[] = ($arr1 !== $arr2) ? "مسئولین: " . (!empty($names1) ? implode('، ', $names1) : '-') . " ← " . (!empty($names2) ? implode('، ', $names2) : '-') : "مسئولین: " . (!empty($names2) ? implode('، ', $names2) : '-'); return implode("\n", $lines); } // public function tasks() // { // $user = User::where('user_name', $_COOKIE['user_identity'])->first(); // $tasks = $user->tasks; // $users = User::get(); // // $state_order = [ // "c73c2044-ea14-42cb-b08d-cecf3d1fdfb5", // "a9ce312f-cfca-491e-8e3d-1975aa6ebc10", // "dea1fb57-a281-4fe7-8f3e-ee5567637e35", // "770fbe42-99f6-41db-9b9e-773d9cced1a5", // "b0e464e1-34eb-41ea-b2f7-3ef7483bc9f0", // "d61d14a3-72f7-4f44-894b-efe8b2a75be1", // ]; // // $work_item = $tasks->whereNull('parent')->sortBy(fn($t) => array_search($t->state, $state_order)); // $sub_work_items = $tasks->whereNotNull('parent')->sortBy(fn($t) => array_search($t->state, $state_order)); // // foreach ($work_item as $w) { // foreach ($sub_work_items as $t) { // foreach ($users as $u) { // if ($t->created_by == $u->plain_id) // $t->created_by = $u->name; // if ($w->created_by == $u->plain_id) // $w->created_by = $u->name; // } // } // } // // return view('tasks.tasks', compact('tasks', 'work_item', 'sub_work_items')); // } public function tasks() { $user = User::where('user_name', $_COOKIE['user_identity'])->first(); if ($user) { if ($user->is_admin == 1) { $tasks = Tasks::with(['duration', 'comments.user']) ->orderBy('target_date', 'desc') ->get(); // dd($tasks); foreach ($tasks as $task) { $totalSeconds = 0; foreach ($task->duration as $item) { if ($item->duration !== null) { $totalSeconds += CarbonInterval::createFromFormat('H:i:s', $item->duration)->totalSeconds; } } $task->totalDuration = CarbonInterval::seconds($totalSeconds)->cascade()->format('%H:%I:%S'); $active_task = TaskDuration::where('task_id', $task->id)->orderBy('start', 'desc')->first(); $task->active = !empty($active_task) && $active_task->end == null; } } else { $tasks = Tasks::with(['duration', 'comments.user'])->where('created_by', $user->id) ->orWhereJsonContains('assignees', (string)$user->id) ->orderBy('target_date', 'desc') ->get(); // dd($tasks); foreach ($tasks as $task) { $totalSeconds = 0; foreach ($task->duration as $item) { if ($user->id == $item->user_id && $item->duration !== null) { $totalSeconds += CarbonInterval::createFromFormat('H:i:s', $item->duration)->totalSeconds; } } $task->totalDuration = CarbonInterval::seconds($totalSeconds)->cascade()->format('%H:%I:%S'); $active_task = TaskDuration::where('task_id', $task->id)->where('user_id', $user->id)->orderBy('start', 'desc')->first(); $task->active = !empty($active_task) && $active_task->end == null; } } $count = count($tasks); // dd((new Tasks())->filterByState($tasks)['backlog'][0], 'count ='.$count); return view('tasks.tasks', [ 'tasks' => (new Tasks())->filterByState($tasks), 'count' => $count, 'user_id' => $user->id, ]); } else { return back()->with('message', [ 'color' => 'red', 'text' => 'کاربر یافت نشد!' ]); } } public function showTask($id) { $task = Tasks::with(['comments.user'])->find($id ?? null); return view('tasks.create', ['task' => $task]); } public function editTask(Request $request) { // dd($request->all()); if (!isset($_COOKIE['user_identity'])) { return back()->with('message', [ 'color' => 'red', 'text' => 'ابتدا باید وارد شوید!' ]); } $actor = User::where('user_name', $_COOKIE['user_identity'])->first(); $data = $request->all(); $task = Tasks::find($data['id'] ?? null); if (!$task) { return back()->with('message', [ 'color' => 'red', 'text' => 'وظیفه یافت نشد!' ]); } $before = $task->toArray(); $data['updated_by'] = $actor?->id; if (array_key_exists('assignees', $data)) { $data['assignees'] = !empty($data['assignees']) ? json_encode($data['assignees']) : null; } else { unset($data['assignees']); } unset($data['_token'], $data['id'], $data['start_date_display'], $data['target_date_display']); $task->update($data); $after = $task->toArray(); $title = $task->title; $message = "تسک «{$title}» برای شما به‌روزرسانی شد."; $message_admin = $this->taskChangeMessage($task, $before, $after, $actor); if (!empty($request->assignees)) { foreach ($request->assignees as $assignee) { $assigneeUser = User::where('id', $assignee)->first(); if ($assigneeUser && $assigneeUser->bale !== null) { $this->send_bale($assigneeUser->bale, $message); } } } // dd($data, $message, $message_admin); $this->send_level1_admins($message_admin); return back()->with('message', [ 'color' => 'green', 'text' => $message ]); } public function createTask() { return view('tasks.create'); } public function deleteTask($id) { Tasks::destroy($id); return response()->json([ "success" => true, "message" => "Task deleted successfully.", "task_id" => 45 ]); } public function storeTask(Request $request) { // dd($request->all()); if (!isset($_COOKIE['user_identity'])) { return back()->with('message', [ 'color' => 'red', 'text' => 'ابتدا باید وارد شوید!' ]); } $user = User::where('user_name', $_COOKIE['user_identity'])->first(); $data = $request->all(); $data['created_by'] = $user->id; $data['assignees'] = !empty($data['assignees']) ? json_encode($data['assignees']) : null; $task = Tasks::create($data); $message = "تسک جدیدی با عنوان {$data['title']} برای شما ایجاد شد."; $deadline = !empty($data['target_date']) ? Jalalian::fromCarbon(Carbon::parse($data['target_date']))->format('Y-m-d') : null; $app = App::find($data['app']); $message_admin = "ایجاد تسک: «{$data['title']}»"; $message_admin .= !empty($app) ? "\nاپ {$app->name_fa}" : null; $message_admin .= !empty($deadline) ? "\nددلاین {$deadline}" : null; $message_admin .= !empty($data['start_date']) ? "\nتاریخ شروع {$data['start_date']}" : null; $message_admin .= !empty($data['state_fa']) ? "\nوضعیت: {$data['state_fa']}" : null; $message_admin .= !empty($data['description']) ? "\nبا توضیحات:\n" . $data['description'] : null; $message_admin .= !empty($data['assignees']) ? "\nتوسط " . $user->name . " ساخته شد و به" : null; if (!empty($data['assignees'])) { foreach ($request->assignees as $assignee) { $user = User::where('id', $assignee)->first(); $message_admin .= "\n$user->name"; if ($user && $user->bale !== null) { $this->send_bale($user->bale, $message); } } $message_admin .= "\nاختصاص یافت."; } else { $message_admin .= "\nتوسط " . $user->name . " ساخته شد"; } // dd($data, $message, $message_admin); $this->send_level1_admins($message_admin); return back()->with('message', [ 'color' => 'green', 'text' => $message ]); } public function activeTask(Request $request) { // dd($request); $user = User::where('user_name', $_COOKIE['user_identity'])->first(); $task = Tasks::find($request->task_id); if (!$task) { return response()->json([ 'action' => 'not_found', 'status' => false ]); } $taskDU = TaskDuration::where('user_id', $user->id) ->where('task_id', $request->task_id) ->orderBy('id', 'desc') ->first(); // اگر رکورد باز داریم => پایان if (!empty($taskDU) && ($taskDU->start !== null && $taskDU->end == null)) { // dd('in if'); $attendance = new Attendance(); $s = Carbon::parse($taskDU->start)->format('H:i:s'); $e = Carbon::parse(now())->format('H:i:s'); $duration = $taskDU->duration; if ($e > $s) { $diff = $attendance->duration($s, $e); if ($duration !== null) { [$h1, $m1, $s1] = explode(':', $duration); $durationSeconds = $h1 * 3600 + $m1 * 60 + $s1; [$h2, $m2, $s2] = explode(':', $diff); $diffSeconds = $h2 * 3600 + $m2 * 60 + $s2; $totalSeconds = $durationSeconds + $diffSeconds; $hours = floor($totalSeconds / 3600); $minutes = floor(($totalSeconds % 3600) / 60); $seconds = $totalSeconds % 60; $duration = sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds); } else { $duration = $diff; } $taskDU->end = now(); $taskDU->duration = $duration; $user->active_task = null; $taskDU->save(); $user->save(); $this->send_level1_admins("پایان تسک: «{$task->title}»\nتوسط: {$user->name}\nمدت این نوبت: {$duration}"); return response()->json([ 'action' => 'ended', 'status' => true, 'duration' => $duration, 'start' => $taskDU->start, 'end' => $taskDU->end, ]); } else return response()->json([ 'action' => 'end', 'status' => false ]); } else { // شروع => همیشه یک رکورد جدید بساز $new_task_duration = TaskDuration::create([ 'task_id' => $task->id, 'user_id' => $user->id, 'start' => now(), 'end' => null, ]); $user->active_task = $task->title; $user->save(); $this->send_level1_admins("شروع تسک: «{$task->title}»\nتوسط: {$user->name}"); return response()->json([ 'action' => 'start', 'status' => true, 'start' => $new_task_duration->start, 'id' => $new_task_duration->id, ]); } return back()->with('message', ['color' => 'red', 'text' => 'وظیفه یافت نشد✖️']); } public function addTask(Request $request) { if (isset($_COOKIE['user_identity'])) { $user = User::where('user_name', $_COOKIE['user_identity'])->first(); } else { return back()->with('message', [ 'color' => 'red', 'text' => 'auth failed!' ]); } $request->validate([ 'title' => 'required', 'description' => 'required', 'assignees' => 'required', 'start_date' => 'required', 'target_date' => 'required', 'priority' => 'required', 'description_html' => 'required', 'completed_at' => 'required', 'state' => 'required', 'created_at' => 'required', 'updated_at' => 'required', 'app' => 'required', 'task_type' => 'required', ]); $data = $request->all(); $data['user_id'] = $user->id; Tasks::create([$data]); return back()->with('message', [ 'color' => 'green', 'text' => 'وظیفه ایجاد شد.' ]); } public function storeComment(Request $request, $id) { if (!isset($_COOKIE['user_identity'])) { return back()->with('message', [ 'color' => 'red', 'text' => 'ابتدا باید وارد شوید!' ]); } $actor = User::where('user_name', $_COOKIE['user_identity'])->first(); $task = Tasks::find($id ?? null); if (!$task) { return back()->with('message', [ 'color' => 'red', 'text' => 'وظیفه یافت نشد!' ]); } $request->validate([ 'body' => 'required|string', ]); $body = trim((string)$request->input('body')); preg_match_all('/@([\p{L}\p{N}_.-]+)/u', $body, $matches); $usernames = array_values(array_unique($matches[1] ?? [])); $mentionedUsers = !empty($usernames) ? User::whereIn('user_name', $usernames)->get() : collect(); $mentionedIds = $mentionedUsers->pluck('id')->values()->all(); TaskComment::create([ 'task_id' => $task->id, 'user_id' => $actor->id, 'body' => $body, 'mentioned_user_ids' => !empty($mentionedIds) ? $mentionedIds : null, ]); $text = "کامنت جدید روی تسک «{$task->title}»\n" . "توسط: {$actor->name}\n\n" . $body; foreach ($mentionedUsers as $mu) { if ($mu->id === $actor->id) { continue; } if ($mu->bale) { $this->send_bale($mu->bale, $text); } } $this->send_level1_admins($text); return back()->with('message', [ 'color' => 'green', 'text' => 'کامنت ثبت شد.' ]); } public function webhookPlane(Request $request) { $d = $request->all(); // فقط وقتی تغییر state هست if (isset($d['event'], $d['action'], $d['data']['name'], $d['data']['state']['name'])) { $msg = "Event: {$d['event']}\nAction: {$d['action']}\nName: {$d['data']['name']}\nNew Status: {$d['data']['state']['name']}"; // ارسال به تلگرام Http::get("https://api.wwwapp.ir/telegran_send.php", [ 'botToken' => "7467099619:AAF2V6yYcbAb8oSIRSCyH5i2GKfdWVO3a7k", 'chatId' => "-4742642674", 'message' => $msg, ]); } // اگر خواستی ثبت در دیتابیس هم اضافه کنی // DB::table('tst')->insert([ // 'data' => json_encode($d, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE), // ]); return response()->json(['status' => 'ok'], 200); } private function send_bale($chat_id, $message) { try { Http::withOptions([ 'curl' => [ CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4, CURLOPT_TCP_FASTOPEN => 1, ] ])->withoutVerifying()->post('https://tapi.bale.ai/1482838710:sYbLzby0tuLRzHvP4d3LsbcNwg2sjSDLTAU/sendMessage', [ "chat_id" => $chat_id, 'text' => $message, ]); } catch (\Exception $e) { } } }