Commit e226894f by Shaganaz

Implement CRUD functionality

parent 21957651
...@@ -30,4 +30,24 @@ public function store(Request $request) ...@@ -30,4 +30,24 @@ public function store(Request $request)
return redirect()->route('admin.users')->with('success', 'User created successfully.'); return redirect()->route('admin.users')->with('success', 'User created successfully.');
} }
public function update(Request $request, User $user)
{
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email,' . $user->id,
'designation' => 'nullable|string|max:255',
'role_id' => 'required|exists:roles,id',
]);
$user->update($request->only(['name', 'email', 'designation', 'role_id']));
return redirect()->route('admin.users')->with('success', 'User updated successfully.');
}
public function delete(User $user)
{
$user->delete();
return redirect()->route('admin.users')->with('success', 'User deleted successfully.');
}
} }
...@@ -31,4 +31,32 @@ public function store(Request $request) ...@@ -31,4 +31,32 @@ public function store(Request $request)
return redirect()->route('admin.projects')->with('success', 'Project created successfully.'); return redirect()->route('admin.projects')->with('success', 'Project created successfully.');
} }
public function update(Request $request, $id)
{
$request->validate([
'name' => 'required|string|max:255',
'slug' => 'required|string|max:255|unique:projects,slug,' . $id,
'description' => 'required|string',
'start_date' => 'required|date',
'end_date' => 'required|date|after_or_equal:start_date',
'created_by' => 'required|exists:users,id',
]);
$project = Project::findOrFail($id);
$project->update($request->only([
'name', 'slug', 'description', 'start_date', 'end_date', 'created_by'
]));
return redirect()->back()->with('success', 'Project updated successfully.');
}
public function delete($id)
{
$project = Project::findOrFail($id);
$project->delete();
return redirect()->back()->with('success', 'Project deleted successfully.');
}
} }
...@@ -59,5 +59,39 @@ public function taskList() ...@@ -59,5 +59,39 @@ public function taskList()
$tasks = Task::with(['project', 'creator', 'assignedUsers', 'files.uploader'])->get(); $tasks = Task::with(['project', 'creator', 'assignedUsers', 'files.uploader'])->get();
return view('admin.task-list', compact('tasks')); return view('admin.task-list', compact('tasks'));
} }
public function update(Request $request, $id)
{
$task = Task::findOrFail($id);
$request->validate([
'project_id' => 'required|exists:projects,id',
'title' => 'required|string|max:255|unique:tasks,title,' . $id,
'description' => 'required|string',
'status' => 'required|string|max:255',
'priority' => 'required|string|max:255',
'due_date' => 'required|date',
'assigned_users' => 'nullable|array',
'assigned_users.*' => 'exists:users,id',
]);
$task->update($request->only(['project_id', 'title', 'description', 'status', 'priority', 'due_date']));
if ($request->has('assigned_users')) {
$task->assignedUsers()->syncWithPivotValues($request->assigned_users, [
'assigned_by' => auth()->id(),
'created_at' => now(),
'updated_at' => now()
]);
}
return redirect()->route('admin.tasks')->with('success', 'Task updated successfully.');
}
public function delete($id)
{
$task = Task::findOrFail($id);
$task->delete();
return redirect()->route('admin.tasks')->with('success', 'Task deleted successfully.');
}
} }
...@@ -51,6 +51,10 @@ public function assignedTasks() ...@@ -51,6 +51,10 @@ public function assignedTasks()
{ {
return $this->belongsToMany(Task::class)->withPivot('assigned_by')->withTimestamps(); return $this->belongsToMany(Task::class)->withPivot('assigned_by')->withTimestamps();
} }
public function uploadedFiles()
{
return $this->hasMany(File::class,'uploaded_by');
}
/** /**
* The attributes that should be cast. * The attributes that should be cast.
* *
......
.projects-container { .projects-container {
max-width: 1000px; max-width: 1200px;
margin: 2rem auto; margin: 40px auto;
padding: 1rem 2rem; padding: 20px;
font-family: Arial, sans-serif; background-color: #fff;
background: #fff;
border-radius: 8px; border-radius: 8px;
box-shadow: 0 2px 8px rgb(0 0 0 / 0.1); text-align: center;
} }
h1 { h1 {
font-size: 1.8rem; font-size: 30px;
margin-bottom: 1rem;
color: #333;
} }
.action-bar { .action-bar {
margin-bottom: 1rem; margin-bottom: 20px;
display: flex; text-align: right;
justify-content: flex-start;
} }
.create-button { .create-button {
background-color: #2563eb; /* Blue */ background-color: #28a745;
color: white; color: black;
font-weight: 600; padding: 10px 16px;
border: none; border: none;
padding: 0.5rem 1rem; border-radius: 5px;
border-radius: 4px; font-size: 14px;
cursor: pointer; cursor: pointer;
transition: background-color 0.3s ease;
}
.create-button:hover {
background-color: #1e40af;
} }
.form-section { .form-section {
margin-bottom: 2rem; margin-bottom: 30px;
border: 1px solid #ddd; padding: 20px;
padding: 1rem; border: 1px solid #ccc;
border-radius: 6px; background-color: #ffffff;
background-color: #fafafa; border-radius: 8px;
} }
.hidden { .hidden {
...@@ -48,82 +39,59 @@ h1 { ...@@ -48,82 +39,59 @@ h1 {
} }
.form-grid { .form-grid {
display: grid; display: flex;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); flex-wrap: wrap;
gap: 1rem 2rem; gap: 20px;
align-items: center;
} }
.form-group { .form-group {
flex: 1 1 45%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.form-group.full-width {
flex: 1 1 100%;
}
.form-group label { .form-group label {
font-weight: 600; margin-bottom: 6px;
margin-bottom: 0.4rem; font-weight: bold;
color: #555;
} }
.form-group input, .form-group input,
.form-group textarea, .form-group textarea,
.form-group select { .form-group select {
padding: 0.5rem; padding: 8px;
border: 1px solid #ccc; border: 1px solid #ccc;
border-radius: 4px; border-radius: 5px;
font-size: 1rem;
transition: border-color 0.2s ease;
}
.form-group input:focus,
.form-group textarea:focus,
.form-group select:focus {
border-color: #2563eb;
outline: none;
box-shadow: 0 0 0 2px rgb(37 99 235 / 0.3);
}
.form-group.full-width {
grid-column: 1 / -1;
} }
.submit-button { .submit-button {
background-color: #10b981; /* Green */ margin-top: 20px;
color: white; background-color: #007bff;
font-weight: 700; color: black;
padding: 10px 16px;
border: none; border: none;
padding: 0.6rem 1.5rem; border-radius: 5px;
border-radius: 4px; font-size: 14px;
cursor: pointer; cursor: pointer;
margin-top: 1rem;
transition: background-color 0.3s ease;
}
.submit-button:hover {
background-color: #047857;
} }
.project-table { .project-table {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
box-shadow: 0 1px 3px rgb(0 0 0 / 0.1); margin-top: 30px;
}
.project-table thead {
background-color: #f3f4f6;
border-bottom: 2px solid #e5e7eb;
} }
.project-table th, .project-table th,
.project-table td { .project-table td {
border: 1px solid #ddd;
padding: 12px;
text-align: left; text-align: left;
padding: 0.75rem 1rem;
border-bottom: 1px solid #e5e7eb;
color: #374151;
font-size: 0.95rem;
} }
.project-table tbody tr:hover { .project-table th {
background-color: #f9fafb; background-color: #f0f0f0;
cursor: default; font-weight: bold;
} }
...@@ -127,3 +127,6 @@ h1 { ...@@ -127,3 +127,6 @@ h1 {
background-color: #f9fafb; background-color: #f9fafb;
cursor: default; cursor: default;
} }
...@@ -50,3 +50,32 @@ ...@@ -50,3 +50,32 @@
.dashboard-button:hover { .dashboard-button:hover {
background-color: #1e40af; background-color: #1e40af;
} }
.user-table input, .user-table select {
width: 100%;
padding: 6px;
border: 1px solid #ccc;
border-radius: 4px;
}
.hidden {
display: none;
}
.edit-btn, .save-btn, .delete-btn {
padding: 6px 10px;
margin: 2px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.display-only {
user-select: none;
pointer-events: none;
}
.edit-btn { background-color: #007bff; color: white; }
.save-btn { background-color: #28a745; color: white; }
.delete-btn { background-color: #dc3545; color: white; }
...@@ -57,22 +57,89 @@ ...@@ -57,22 +57,89 @@
<th>Start Date</th> <th>Start Date</th>
<th>End Date</th> <th>End Date</th>
<th>Created By</th> <th>Created By</th>
<th>Actions</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@foreach ($projects as $project) @foreach ($projects as $project)
<tr> <tr>
<form id="form-{{ $project->id }}" action="{{ route('admin.projects.update', $project->id) }}" method="POST">
@csrf
@method('PUT')
<td>{{ $project->id }}</td> <td>{{ $project->id }}</td>
<td>{{ $project->name }}</td>
<td>{{ $project->slug }}</td> <td>
<td>{{ Str::limit($project->description, 50) }}</td> <span class="display-only" id="name-label-{{ $project->id }}">{{ $project->name }}</span>
<td>{{ $project->start_date }}</td> <input type="text" name="name" value="{{ $project->name }}" class="edit-only hidden" id="name-input-{{ $project->id }}">
<td>{{ $project->end_date }}</td> </td>
<td>{{ $project->creator->name }}</td>
<td>
<span class="display-only" id="slug-label-{{ $project->id }}">{{ $project->slug }}</span>
<input type="text" name="slug" value="{{ $project->slug }}" class="edit-only hidden" id="slug-input-{{ $project->id }}">
</td>
<td>
<span class="display-only" id="desc-label-{{ $project->id }}">{{ Str::limit($project->description, 50) }}</span>
<textarea name="description" rows="2" class="edit-only hidden" id="desc-input-{{ $project->id }}">{{ $project->description }}</textarea>
</td>
<td>
<span class="display-only" id="start-label-{{ $project->id }}">{{ $project->start_date }}</span>
<input type="datetime-local" name="start_date" value="{{ \Carbon\Carbon::parse($project->start_date)->format('Y-m-d\TH:i') }}" class="edit-only hidden" id="start-input-{{ $project->id }}">
</td>
<td>
<span class="display-only" id="end-label-{{ $project->id }}">{{ $project->end_date }}</span>
<input type="datetime-local" name="end_date" value="{{ \Carbon\Carbon::parse($project->end_date)->format('Y-m-d\TH:i') }}" class="edit-only hidden" id="end-input-{{ $project->id }}">
</td>
<td>
<span class="display-only" id="creator-label-{{ $project->id }}">{{ $project->creator->name }}</span>
<select name="created_by" class="edit-only hidden" id="creator-input-{{ $project->id }}">
@foreach($users as $user)
<option value="{{ $user->id }}" {{ $project->created_by == $user->id ? 'selected' : '' }}>
{{ $user->name }}
</option>
@endforeach
</select>
</td>
<td>
<button type="button" onclick="enableProjectEditing('{{ $project->id }}')" class="edit-btn">Edit</button>
<button type="submit" class="save-btn hidden" id="save-{{ $project->id }}">Save</button>
</td>
</form>
<td>
<form action="{{ route('admin.projects.delete', $project->id) }}" method="POST" style="display:inline;">
@csrf
@method('DELETE')
<button type="submit" onclick="return confirm('Delete this project?')" class="delete-btn">Delete</button>
</form>
</td>
</tr> </tr>
@endforeach @endforeach
</tbody> </tbody>
</table> </table>
</div> </div>
</x-app-layout> </x-app-layout>
<script>
function enableProjectEditing(projectId) {
document.getElementById(`name-label-${projectId}`).classList.add('hidden');
document.getElementById(`slug-label-${projectId}`).classList.add('hidden');
document.getElementById(`desc-label-${projectId}`).classList.add('hidden');
document.getElementById(`start-label-${projectId}`).classList.add('hidden');
document.getElementById(`end-label-${projectId}`).classList.add('hidden');
document.getElementById(`creator-label-${projectId}`).classList.add('hidden');
document.getElementById(`name-input-${projectId}`).classList.remove('hidden');
document.getElementById(`slug-input-${projectId}`).classList.remove('hidden');
document.getElementById(`desc-input-${projectId}`).classList.remove('hidden');
document.getElementById(`start-input-${projectId}`).classList.remove('hidden');
document.getElementById(`end-input-${projectId}`).classList.remove('hidden');
document.getElementById(`creator-input-${projectId}`).classList.remove('hidden');
document.getElementById(`save-${projectId}`).classList.remove('hidden');
}
</script>
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Status</label> <label>Status</label>
<input type="text" name="status" placeholder="e.g.pending, in-progress,completed" required> <input type="text" name="status" placeholder="e.g. pending, in-progress, completed" required>
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Priority</label> <label>Priority</label>
...@@ -60,48 +60,103 @@ ...@@ -60,48 +60,103 @@
<tr> <tr>
<th>ID</th> <th>ID</th>
<th>Project</th> <th>Project</th>
<th>Task Title</th> <th>Title</th>
<th>Task Description</th> <th>Description</th>
<th>Status</th> <th>Status</th>
<th>Priority</th> <th>Priority</th>
<th>Due Date</th> <th>Due Date</th>
<th>Created By</th> <th>Created By</th>
<th>Assign Task To The User</th> <th>Assigned Users</th>
<th>Actions</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@foreach ($tasks as $task) @foreach ($tasks as $task)
<form action="{{ route('admin.tasks.update', $task->id) }}" method="POST">
@csrf
@method('PUT')
<tr> <tr>
<td>{{ $task->id }}</td> <td>{{ $task->id }}</td>
<td>{{ $task->project->name }}</td> <td>
<td>{{ $task->title }}</td> <span class="display-only" id="project-label-{{ $task->id }}">{{ $task->project->name }}</span>
<td>{{ Str::limit($task->description, 50) }}</td> <select name="project_id" class="edit-only hidden" id="project-input-{{ $task->id }}">
<td>{{ $task->status }}</td> @foreach($projects as $project)
<td>{{ $task->priority }}</td> <option value="{{ $project->id }}" {{ $task->project_id == $project->id ? 'selected' : '' }}>{{ $project->name }}</option>
<td>{{ $task->due_date }}</td> @endforeach
</select>
</td>
<td>
<span class="display-only" id="title-label-{{ $task->id }}">{{ $task->title }}</span>
<input type="text" name="title" value="{{ $task->title }}" class="edit-only hidden" id="title-input-{{ $task->id }}">
</td>
<td>
<span class="display-only" id="desc-label-{{ $task->id }}">{{ Str::limit($task->description, 50) }}</span>
<textarea name="description" class="edit-only hidden" id="desc-input-{{ $task->id }}">{{ $task->description }}</textarea>
</td>
<td>
<span class="display-only" id="status-label-{{ $task->id }}">{{ $task->status }}</span>
<input type="text" name="status" value="{{ $task->status }}" class="edit-only hidden" id="status-input-{{ $task->id }}">
</td>
<td>
<span class="display-only" id="priority-label-{{ $task->id }}">{{ $task->priority }}</span>
<input type="text" name="priority" value="{{ $task->priority }}" class="edit-only hidden" id="priority-input-{{ $task->id }}">
</td>
<td>
<span class="display-only" id="due-label-{{ $task->id }}">{{ $task->due_date }}</span>
<input type="datetime-local" name="due_date" value="{{ \Carbon\Carbon::parse($task->due_date)->format('Y-m-d\TH:i') }}" class="edit-only hidden" id="due-input-{{ $task->id }}">
</td>
<td>{{ $task->creator->name }}</td> <td>{{ $task->creator->name }}</td>
<td> <td>
<span class="display-only" id="assigned-label-{{ $task->id }}">
@if ($task->assignedUsers->isNotEmpty()) @if ($task->assignedUsers->isNotEmpty())
@foreach ($task->assignedUsers as $user) @foreach ($task->assignedUsers as $user)
<span>{{ $user->name }}</span><br> <span>{{ $user->name }}</span><br>
@endforeach @endforeach
@else @else
<form action="{{ route('admin.tasks.assign', $task->id) }}" method="POST"> <em style="color: gray;">Not Assigned</em>
@csrf @endif
<select name="assigned_users[]" multiple required> </span>
<select name="assigned_users[]" class="edit-only hidden" id="assigned-input-{{ $task->id }}" multiple>
@foreach($users as $user) @foreach($users as $user)
<option value="{{ $user->id }}">{{ $user->name }}</option> <option value="{{ $user->id }}" {{ $task->assignedUsers->pluck('id')->contains($user->id) ? 'selected' : '' }}>{{ $user->name }}</option>
@endforeach @endforeach
</select> </select>
<button type="submit" class="submit-button">Assign Task</button> </td>
<td>
<button type="button" onclick="enableTaskEditing('{{ $task->id }}')" class="edit-btn">Edit</button>
<button type="submit" class="save-btn hidden" id="save-{{ $task->id }}">Save</button>
</form>
<form action="{{ route('admin.tasks.delete', $task->id) }}" method="POST" style="display:inline;">
@csrf
@method('DELETE')
<button type="submit" onclick="return confirm('Delete this task?')" class="delete-btn">Delete</button>
</form> </form>
@endif
</td> </td>
</tr> </tr>
@endforeach @endforeach
</tbody> </tbody>
</table> </table>
</div> </div>
</x-app-layout> </x-app-layout>
<script>
function enableTaskEditing(taskId) {
document.getElementById(`project-label-${taskId}`).classList.add('hidden');
document.getElementById(`title-label-${taskId}`).classList.add('hidden');
document.getElementById(`desc-label-${taskId}`).classList.add('hidden');
document.getElementById(`status-label-${taskId}`).classList.add('hidden');
document.getElementById(`priority-label-${taskId}`).classList.add('hidden');
document.getElementById(`due-label-${taskId}`).classList.add('hidden');
document.getElementById(`assigned-label-${taskId}`).classList.add('hidden');
document.getElementById(`project-input-${taskId}`).classList.remove('hidden');
document.getElementById(`title-input-${taskId}`).classList.remove('hidden');
document.getElementById(`desc-input-${taskId}`).classList.remove('hidden');
document.getElementById(`status-input-${taskId}`).classList.remove('hidden');
document.getElementById(`priority-input-${taskId}`).classList.remove('hidden');
document.getElementById(`due-input-${taskId}`).classList.remove('hidden');
document.getElementById(`assigned-input-${taskId}`).classList.remove('hidden');
document.getElementById(`save-${taskId}`).classList.remove('hidden');
}
</script>
...@@ -55,15 +55,75 @@ ...@@ -55,15 +55,75 @@
<tbody> <tbody>
@foreach ($users as $user) @foreach ($users as $user)
<tr> <tr>
<form id="form-{{ $user->id }}" action="{{ route('admin.users.update', $user->id) }}" method="POST">
@csrf
@method('PUT')
<td>{{ $user->id }}</td> <td>{{ $user->id }}</td>
<td>{{ $user->name }}</td>
<td>{{ $user->email }}</td> <td>
<td>{{ $user->designation }}</td> <span class="display-only" id="name-label-{{ $user->id }}">{{ $user->name }}</span>
<td>{{ $user->role->name }}</td> <input type="text" name="name" value="{{ $user->name }}" class="edit-only hidden" id="name-input-{{ $user->id }}">
</td>
<td>
<span class="display-only" id="email-label-{{ $user->id }}">{{ $user->email }}</span>
<input type="email" name="email" value="{{ $user->email }}" class="edit-only hidden" id="email-input-{{ $user->id }}">
</td>
<td>
<span class="display-only" id="designation-label-{{ $user->id }}">{{ $user->designation }}</span>
<input type="text" name="designation" value="{{ $user->designation }}" class="edit-only hidden" id="designation-input-{{ $user->id }}">
</td>
<td>
<span class="display-only" id="role-label-{{ $user->id }}">{{ $user->role->name }}</span>
<select name="role_id" class="edit-only hidden" id="role-input-{{ $user->id }}">
@foreach($roles as $role)
<option value="{{ $role->id }}" {{ $user->role_id == $role->id ? 'selected' : '' }}>
{{ $role->name }}
</option>
@endforeach
</select>
</td>
<td>
<button type="button" onclick="enableEditing('{{ $user->id }}')" class="edit-btn">Edit</button>
<button type="submit" class="save-btn hidden" id="save-{{ $user->id }}">Save</button>
</td>
</form>
<td>
<form action="{{ route('admin.users.delete', $user->id) }}" method="POST" style="display:inline;">
@csrf
@method('DELETE')
<button type="submit" onclick="return confirm('Delete this user?')" class="delete-btn">Delete</button>
</form>
</td>
</tr> </tr>
@endforeach @endforeach
</tbody> </tbody>
</table> </table>
</div> </div>
</x-app-layout> </x-app-layout>
<script>
function enableEditing(userId) {
document.getElementById(`name-label-${userId}`).classList.add('hidden');
document.getElementById(`email-label-${userId}`).classList.add('hidden');
document.getElementById(`designation-label-${userId}`).classList.add('hidden');
document.getElementById(`role-label-${userId}`).classList.add('hidden');
document.getElementById(`name-input-${userId}`).classList.remove('hidden');
document.getElementById(`email-input-${userId}`).classList.remove('hidden');
document.getElementById(`designation-input-${userId}`).classList.remove('hidden');
document.getElementById(`role-input-${userId}`).classList.remove('hidden');
document.getElementById(`save-${userId}`).classList.remove('hidden');
}
</script>
...@@ -54,11 +54,18 @@ ...@@ -54,11 +54,18 @@
Route::get('/users', [AdminUserController::class, 'index'])->name('admin.users'); Route::get('/users', [AdminUserController::class, 'index'])->name('admin.users');
Route::post('/users', [AdminUserController::class, 'store'])->name('admin.users.store'); Route::post('/users', [AdminUserController::class, 'store'])->name('admin.users.store');
Route::put('/users/{user}', [AdminUserController::class, 'update'])->name('admin.users.update');
Route::delete('/users/{user}', [AdminUserController::class, 'delete'])->name('admin.users.delete');
Route::get('projects', [ProjectController::class, 'index'])->name('admin.projects'); Route::get('projects', [ProjectController::class, 'index'])->name('admin.projects');
Route::post('projects', [ProjectController::class, 'store'])->name('admin.projects.store'); Route::post('projects', [ProjectController::class, 'store'])->name('admin.projects.store');
Route::put('/admin/projects/{id}', [ProjectController::class, 'update'])->name('admin.projects.update');
Route::delete('/admin/projects/{id}', [ProjectController::class, 'delete'])->name('admin.projects.delete');
Route::get('tasks', [TaskController::class, 'index'])->name('admin.tasks'); Route::get('tasks', [TaskController::class, 'index'])->name('admin.tasks');
Route::post('tasks', [TaskController::class, 'store'])->name('admin.tasks.store'); Route::post('tasks', [TaskController::class, 'store'])->name('admin.tasks.store');
Route::post('tasks/{task}/assign', [TaskController::class, 'assignUsers'])->name('admin.tasks.assign'); Route::post('tasks/{task}/assign', [TaskController::class, 'assignUsers'])->name('admin.tasks.assign');
Route::put('/admin/tasks/{id}', [TaskController::class, 'update'])->name('admin.tasks.update');
Route::delete('/admin/tasks/{id}', [TaskController::class, 'delete'])->name('admin.tasks.delete');
Route::get('/tasks/list', [TaskController::class, 'taskList'])->name('admin.tasks.list'); Route::get('/tasks/list', [TaskController::class, 'taskList'])->name('admin.tasks.list');
}); });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment