feat: implement full project management suite with module/task CRUD, progress tracking, and admin view toggling

This commit is contained in:
Ümit Tunç
2026-07-30 17:28:30 +03:00
parent 26cab615f1
commit 483b0518fd
2 changed files with 640 additions and 124 deletions
+178 -6
View File
@@ -3,29 +3,32 @@
namespace App\Http\Controllers;
use App\Models\Project;
use App\Models\ProjectModule;
use App\Models\ProjectTask;
use App\Models\ProjectUpdate;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class ProjectController extends Controller
{
/**
* Display the public/client project tracking portal.
* Display the public/client project tracking portal & manager view.
*/
public function show(Request $request, string $slug)
{
$project = Project::where('slug', $slug)
->with(['modules', 'tasks', 'updates' => function($q) {
$q->where('is_public', true)->latest();
$q->latest();
}, 'proposal'])
->firstOrFail();
// Recalculate progress dynamically
$project->recalculateProgress();
// Check if access code protection is active and verified in session
$sessionKey = 'project_access_' . $project->id;
$isVerified = session()->get($sessionKey, true); // Verified by default for link convenience
// Check if admin mode is active (logged in user OR session toggle)
$isAdminMode = Auth::check() || session()->get('admin_mode_' . $project->id, true);
return view('projects.show', compact('project', 'isVerified'));
return view('projects.show', compact('project', 'isAdminMode'));
}
/**
@@ -46,4 +49,173 @@ class ProjectController extends Controller
return back()->withErrors(['access_code' => 'Geçersiz müşteri takip şifresi.']);
}
/**
* Web Manager Action: Update Module Status (Bekliyor / Devam Ediyor / Tamamlandı)
*/
public function updateModuleStatus(Request $request, string $slug)
{
$project = Project::where('slug', $slug)->firstOrFail();
$request->validate([
'module_id' => 'required|exists:project_modules,id',
'status' => 'required|in:pending,in_progress,completed',
]);
$module = ProjectModule::where('id', $request->input('module_id'))
->where('project_id', $project->id)
->firstOrFail();
$module->update(['status' => $request->input('status')]);
// Recalculate overall progress %
$newProgress = $project->recalculateProgress();
if ($request->wantsJson() || $request->ajax()) {
return response()->json([
'success' => true,
'message' => "'{$module->title}' modül durumu güncellendi.",
'progress_percent' => $newProgress,
]);
}
return back()->with('success', "'{$module->title}' modül durumu güncellendi.");
}
/**
* Web Manager Action: Update Task Status (Kanban Move)
*/
public function updateTaskStatus(Request $request, string $slug)
{
$project = Project::where('slug', $slug)->firstOrFail();
$request->validate([
'task_id' => 'required|exists:project_tasks,id',
'status' => 'required|in:todo,in_progress,review,done',
]);
$task = ProjectTask::where('id', $request->input('task_id'))
->where('project_id', $project->id)
->firstOrFail();
$task->update(['status' => $request->input('status')]);
$newProgress = $project->recalculateProgress();
if ($request->wantsJson() || $request->ajax()) {
return response()->json([
'success' => true,
'message' => "'{$task->title}' görev durumu güncellendi.",
'progress_percent' => $newProgress,
'counts' => [
'todo' => $project->tasks()->where('status', 'todo')->count(),
'in_progress' => $project->tasks()->where('status', 'in_progress')->count(),
'review' => $project->tasks()->where('status', 'review')->count(),
'done' => $project->tasks()->where('status', 'done')->count(),
]
]);
}
return back()->with('success', "'{$task->title}' görev durumu güncellendi.");
}
/**
* Web Manager Action: Add New Task
*/
public function addTask(Request $request, string $slug)
{
$project = Project::where('slug', $slug)->firstOrFail();
$request->validate([
'title' => 'required|string|max:255',
'description' => 'nullable|string|max:2000',
'status' => 'required|in:todo,in_progress,review,done',
'priority' => 'required|in:low,medium,high,urgent',
'assigned_person' => 'nullable|string|max:255',
'project_module_id' => 'nullable|exists:project_modules,id',
]);
$task = ProjectTask::create([
'project_id' => $project->id,
'project_module_id' => $request->input('project_module_id'),
'title' => $request->input('title'),
'description' => $request->input('description'),
'status' => $request->input('status'),
'priority' => $request->input('priority'),
'assigned_person' => $request->input('assigned_person'),
]);
$project->recalculateProgress();
return back()->with('success', "'{$task->title}' görevi panoya eklendi.");
}
/**
* Web Manager Action: Delete Task
*/
public function deleteTask(Request $request, string $slug)
{
$project = Project::where('slug', $slug)->firstOrFail();
$request->validate([
'task_id' => 'required|exists:project_tasks,id',
]);
$task = ProjectTask::where('id', $request->input('task_id'))
->where('project_id', $project->id)
->firstOrFail();
$taskName = $task->title;
$task->delete();
$project->recalculateProgress();
return back()->with('success', "'{$taskName}' görevi silindi.");
}
/**
* Web Manager Action: Add Live Progress Update / Announcement
*/
public function addUpdate(Request $request, string $slug)
{
$project = Project::where('slug', $slug)->firstOrFail();
$request->validate([
'title' => 'required|string|max:255',
'content' => 'required|string|max:5000',
]);
ProjectUpdate::create([
'project_id' => $project->id,
'user_id' => Auth::id(),
'title' => $request->input('title'),
'content' => $request->input('content'),
'progress_percent_at_update' => $project->progress_percent,
'is_public' => true,
]);
return back()->with('success', 'Yeni ilerleme duyurusu yayınlandı.');
}
/**
* Web Manager Action: Recalculate Progress %
*/
public function recalculate(Request $request, string $slug)
{
$project = Project::where('slug', $slug)->firstOrFail();
$pct = $project->recalculateProgress();
return back()->with('success', "Proje ilerleme yüzdesi yeniden hesaplandı: %{$pct}");
}
/**
* Toggle Admin / Client View Mode in session
*/
public function toggleAdminMode(Request $request, string $slug)
{
$project = Project::where('slug', $slug)->firstOrFail();
$key = 'admin_mode_' . $project->id;
$current = session()->get($key, true);
session()->put($key, !$current);
return back();
}
}