Spaces:
Build error
Build error
Commit
·
dd18d72
1
Parent(s):
60c127b
added taskpracticed functionality
Browse files
app/Http/Controllers/DashboardController.php
CHANGED
|
@@ -7,6 +7,7 @@
|
|
| 7 |
use App\Models\Skill;
|
| 8 |
use App\Models\Task;
|
| 9 |
use Auth;
|
|
|
|
| 10 |
|
| 11 |
class DashboardController extends Controller
|
| 12 |
{
|
|
@@ -63,7 +64,7 @@ public function skill($id){
|
|
| 63 |
}
|
| 64 |
|
| 65 |
// get the list of tasks which belongs to this particular skill
|
| 66 |
-
$tasks = Task::where('skill_id',$current_skill->id)->get();
|
| 67 |
|
| 68 |
return view('dashboard.skill',[
|
| 69 |
'skill' => $current_skill,
|
|
@@ -71,4 +72,90 @@ public function skill($id){
|
|
| 71 |
]);
|
| 72 |
|
| 73 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
}
|
|
|
|
| 7 |
use App\Models\Skill;
|
| 8 |
use App\Models\Task;
|
| 9 |
use Auth;
|
| 10 |
+
use Carbon\Carbon;
|
| 11 |
|
| 12 |
class DashboardController extends Controller
|
| 13 |
{
|
|
|
|
| 64 |
}
|
| 65 |
|
| 66 |
// get the list of tasks which belongs to this particular skill
|
| 67 |
+
$tasks = Task::where('skill_id',$current_skill->id)->orderby('updated_at',"DESC")->get();
|
| 68 |
|
| 69 |
return view('dashboard.skill',[
|
| 70 |
'skill' => $current_skill,
|
|
|
|
| 72 |
]);
|
| 73 |
|
| 74 |
}
|
| 75 |
+
|
| 76 |
+
public function createTask(Request $request,$skill_id){
|
| 77 |
+
// $request includes title, task_type
|
| 78 |
+
|
| 79 |
+
// validate
|
| 80 |
+
$request->validate([
|
| 81 |
+
'title' => [
|
| 82 |
+
'required',
|
| 83 |
+
'string',
|
| 84 |
+
],
|
| 85 |
+
'task_type' => [
|
| 86 |
+
'required',
|
| 87 |
+
'string',
|
| 88 |
+
'in:basic,sub,app'
|
| 89 |
+
],
|
| 90 |
+
]);
|
| 91 |
+
|
| 92 |
+
//
|
| 93 |
+
$current_skill = Skill::where(
|
| 94 |
+
'belongs_to',
|
| 95 |
+
Auth::guard('customuser')->user()->username)->where(
|
| 96 |
+
'id',
|
| 97 |
+
$skill_id
|
| 98 |
+
)->first();
|
| 99 |
+
|
| 100 |
+
if($current_skill==null){
|
| 101 |
+
return redirect(route('dashboard.myskills')); // skill not found
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
// create task
|
| 105 |
+
$task = new Task();
|
| 106 |
+
$task->title = $request->title;
|
| 107 |
+
$task->type = $request->task_type;
|
| 108 |
+
$task->skill_id = $skill_id;
|
| 109 |
+
|
| 110 |
+
$task->save();
|
| 111 |
+
|
| 112 |
+
return redirect()->back();
|
| 113 |
+
// return redirect(route('dashboard.skill',$id));
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
public function taskDetail($task_id){
|
| 117 |
+
$task = Task::where("id",$task_id)->first();
|
| 118 |
+
if($task==null){
|
| 119 |
+
abort(404);
|
| 120 |
+
}
|
| 121 |
+
return $task->toArray();
|
| 122 |
+
}
|
| 123 |
+
public function taskPracticed(Request $request){
|
| 124 |
+
// $request includes task_id
|
| 125 |
+
|
| 126 |
+
// validate
|
| 127 |
+
$request->validate([
|
| 128 |
+
'task_id'=>[
|
| 129 |
+
'required',
|
| 130 |
+
'string',
|
| 131 |
+
'exists:App\Models\Task,id',
|
| 132 |
+
]
|
| 133 |
+
]);
|
| 134 |
+
|
| 135 |
+
// check if it has been a given amount of time since they last practiced
|
| 136 |
+
$minutes = 2;
|
| 137 |
+
$task = Task::where('id',$request->task_id);
|
| 138 |
+
$task = $task->first();
|
| 139 |
+
|
| 140 |
+
// do this except the first time
|
| 141 |
+
if($task->practice_count>0){
|
| 142 |
+
$task = Task::where('id',$request->task_id);
|
| 143 |
+
$task = $task->where('updated_at','<=',Carbon::now()->subMinutes($minutes)->toDateTimeString()); // only those who are old
|
| 144 |
+
$task = $task->first();
|
| 145 |
+
}
|
| 146 |
+
|
| 147 |
+
if($task==null){
|
| 148 |
+
// try again later in some time
|
| 149 |
+
return redirect()->back()->withErrors([
|
| 150 |
+
'message'=>"you can only practice a task again after $minutes minutes",
|
| 151 |
+
]);
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
$task->practice_count+=1;
|
| 155 |
+
$task->save();
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
return redirect()->back();
|
| 159 |
+
|
| 160 |
+
}
|
| 161 |
}
|
database/migrations/2024_01_02_075201_create_tasks_table.php
CHANGED
|
@@ -15,6 +15,7 @@ public function up(): void
|
|
| 15 |
$table->id();
|
| 16 |
$table->string('title');
|
| 17 |
$table->string('type');
|
|
|
|
| 18 |
$table->string('skill_id');
|
| 19 |
$table->foreign('skill_id')->on('skills')->references('id')->onDelete('cascade');
|
| 20 |
|
|
|
|
| 15 |
$table->id();
|
| 16 |
$table->string('title');
|
| 17 |
$table->string('type');
|
| 18 |
+
$table->integer('practice_count')->default(0);
|
| 19 |
$table->string('skill_id');
|
| 20 |
$table->foreign('skill_id')->on('skills')->references('id')->onDelete('cascade');
|
| 21 |
|
public/css/dashboard/skill.css
CHANGED
|
@@ -67,12 +67,17 @@ .task{
|
|
| 67 |
margin-left:0;
|
| 68 |
width: 18ch;
|
| 69 |
cursor: pointer;
|
|
|
|
|
|
|
| 70 |
}
|
| 71 |
.task>span{
|
| 72 |
text-align: center;
|
|
|
|
|
|
|
|
|
|
| 73 |
}
|
| 74 |
|
| 75 |
-
#modal{
|
| 76 |
position: absolute;
|
| 77 |
top:50%;
|
| 78 |
left:50%;
|
|
@@ -81,17 +86,17 @@ #modal{
|
|
| 81 |
outline: none;
|
| 82 |
border-radius: 10px;
|
| 83 |
padding:2rem;
|
| 84 |
-
background-color: #
|
| 85 |
}
|
| 86 |
|
| 87 |
-
#modal>.close_btn{
|
| 88 |
position:absolute;
|
| 89 |
top:10px;
|
| 90 |
right:10px;
|
| 91 |
cursor: pointer;
|
| 92 |
}
|
| 93 |
|
| 94 |
-
#modal>.container{
|
| 95 |
display: flex;
|
| 96 |
flex-direction: column;
|
| 97 |
align-items: center;
|
|
@@ -130,10 +135,69 @@ #modal .submit_btn{
|
|
| 130 |
}
|
| 131 |
|
| 132 |
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 136 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
|
|
|
|
|
|
|
| 139 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
margin-left:0;
|
| 68 |
width: 18ch;
|
| 69 |
cursor: pointer;
|
| 70 |
+
border:none;
|
| 71 |
+
display: block;
|
| 72 |
}
|
| 73 |
.task>span{
|
| 74 |
text-align: center;
|
| 75 |
+
font-size: 1rem;
|
| 76 |
+
font-weight: 600;
|
| 77 |
+
color: rgb(90, 90, 90);
|
| 78 |
}
|
| 79 |
|
| 80 |
+
#modal,#task_modal{
|
| 81 |
position: absolute;
|
| 82 |
top:50%;
|
| 83 |
left:50%;
|
|
|
|
| 86 |
outline: none;
|
| 87 |
border-radius: 10px;
|
| 88 |
padding:2rem;
|
| 89 |
+
background-color: #fafafa;
|
| 90 |
}
|
| 91 |
|
| 92 |
+
#modal>.close_btn , #task_modal>.close_btn{
|
| 93 |
position:absolute;
|
| 94 |
top:10px;
|
| 95 |
right:10px;
|
| 96 |
cursor: pointer;
|
| 97 |
}
|
| 98 |
|
| 99 |
+
#modal>.container , #task_modal>.container{
|
| 100 |
display: flex;
|
| 101 |
flex-direction: column;
|
| 102 |
align-items: center;
|
|
|
|
| 135 |
}
|
| 136 |
|
| 137 |
|
| 138 |
+
|
| 139 |
+
|
| 140 |
+
#task_modal .title{
|
| 141 |
+
font-size:2rem;
|
| 142 |
+
margin-bottom: 1rem;
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
#task_modal .practice_btn{
|
| 146 |
+
border-radius: 50px;
|
| 147 |
+
border: none;
|
| 148 |
+
outline: none;
|
| 149 |
+
background-color: #2b60f2;
|
| 150 |
+
color: #fff;
|
| 151 |
+
padding:0.7rem 1.5rem;
|
| 152 |
+
margin-top: 1rem;
|
| 153 |
+
cursor: pointer;
|
| 154 |
+
}
|
| 155 |
+
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
#error_container{
|
| 159 |
+
height:80%;
|
| 160 |
+
position: fixed;
|
| 161 |
+
bottom: 40px;
|
| 162 |
+
right: 30px;
|
| 163 |
+
display: flex;
|
| 164 |
+
flex-direction: column;
|
| 165 |
+
align-items: end;
|
| 166 |
+
justify-content: end;
|
| 167 |
+
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
#error_container>.error{
|
| 171 |
+
min-width:100px;
|
| 172 |
+
min-height:50px;
|
| 173 |
+
width:fit-content;
|
| 174 |
+
background-color: #fff;
|
| 175 |
+
box-shadow: 0px 0px 10px -5px #000;
|
| 176 |
+
border-radius: 10px;
|
| 177 |
+
display: flex;
|
| 178 |
+
align-items: center;
|
| 179 |
+
margin: 6px 0;
|
| 180 |
}
|
| 181 |
+
#error_container>.error>i{
|
| 182 |
+
background-color: red;
|
| 183 |
+
color:#fafafa;
|
| 184 |
+
|
| 185 |
+
padding:0.3rem;
|
| 186 |
+
margin: 1rem;
|
| 187 |
|
| 188 |
+
border-radius:50%;
|
| 189 |
+
width:2rem;
|
| 190 |
+
aspect-ratio: 1;
|
| 191 |
+
display: flex;
|
| 192 |
+
align-items: center;
|
| 193 |
+
justify-content: center;
|
| 194 |
+
}
|
| 195 |
|
| 196 |
+
#error_container>.error>span{
|
| 197 |
+
margin-right: 1rem;
|
| 198 |
|
| 199 |
+
}
|
| 200 |
+
.error_msg{
|
| 201 |
+
color: red;
|
| 202 |
+
font-size:0.8rem;
|
| 203 |
+
}
|
public/js/dashboard/skill.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
function showTask(task_id){
|
| 2 |
+
fetch(`${taskdetail_url}/${task_id}`,{
|
| 3 |
+
method:"GET",
|
| 4 |
+
}).then(res=>res.json()).then((res)=>{
|
| 5 |
+
// console.log(res);
|
| 6 |
+
title_elem = task_modal.querySelector(".title");
|
| 7 |
+
count_elem = task_modal.querySelector(".count");
|
| 8 |
+
task_id_elem = task_modal.querySelector('#task_id');
|
| 9 |
+
|
| 10 |
+
title_elem.innerText = res['title'];
|
| 11 |
+
count_elem.innerText = res['practice_count'];
|
| 12 |
+
|
| 13 |
+
// task_id_elem.value = "bye";
|
| 14 |
+
task_id_elem.value = res['id'];
|
| 15 |
+
// console.log(res['id']);
|
| 16 |
+
|
| 17 |
+
task_modal.showModal();
|
| 18 |
+
|
| 19 |
+
})
|
| 20 |
+
|
| 21 |
+
}
|
| 22 |
+
function closeTask(){
|
| 23 |
+
task_modal.close();
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
function addError(msg){
|
| 28 |
+
// <div class="error">
|
| 29 |
+
// <i class="fa-solid fa-xmark"></i>
|
| 30 |
+
// <span>error see</span>
|
| 31 |
+
// </div>
|
| 32 |
+
|
| 33 |
+
var error_elem = document.createElement('div');
|
| 34 |
+
error_elem.className = 'error';
|
| 35 |
+
error_elem.innerHTML += `<i class="fa-solid fa-xmark"></i>`;
|
| 36 |
+
error_elem.innerHTML += `<span>${msg}</span>`;
|
| 37 |
+
|
| 38 |
+
error_container.append(error_elem);
|
| 39 |
+
|
| 40 |
+
setTimeout(function(){
|
| 41 |
+
error_elem.remove(); // remove after 7 seconds
|
| 42 |
+
},1000*7);
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
|
public/js/home.js
CHANGED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
function showTask(){
|
| 2 |
+
task_modal.showModal();
|
| 3 |
+
}
|
| 4 |
+
function closeTask(){
|
| 5 |
+
task_modal.close();
|
| 6 |
+
}
|
resources/views/dashboard/skill.blade.php
CHANGED
|
@@ -18,7 +18,13 @@
|
|
| 18 |
<button class="new_btn" onclick="modal.showModal()">New</button>
|
| 19 |
</div>
|
| 20 |
<div class="tasks">
|
| 21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
<span>learn how fret works</span>
|
| 23 |
</div>
|
| 24 |
<div class='task'>
|
|
@@ -26,15 +32,15 @@
|
|
| 26 |
</div>
|
| 27 |
<div class='task'>
|
| 28 |
<span>learn guitar string names</span>
|
| 29 |
-
</div>
|
| 30 |
|
| 31 |
</div>
|
| 32 |
</div>
|
| 33 |
</section>
|
| 34 |
<dialog id="modal">
|
| 35 |
<i onclick="modal.close()" class="fa-solid fa-xmark close_btn"></i>
|
| 36 |
-
|
| 37 |
-
|
| 38 |
@csrf
|
| 39 |
<p class='title'>
|
| 40 |
New Task
|
|
@@ -55,7 +61,7 @@
|
|
| 55 |
<option value="app">Application</option>
|
| 56 |
</select>
|
| 57 |
<span class='error_msg'>
|
| 58 |
-
@error('
|
| 59 |
{{ $message }}
|
| 60 |
@enderror
|
| 61 |
</span>
|
|
@@ -63,10 +69,32 @@
|
|
| 63 |
<input type='submit' class='submit_btn' value='Add'>
|
| 64 |
</form>
|
| 65 |
</dialog>
|
| 66 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
<script>
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
</script>
|
| 72 |
@endsection
|
|
|
|
| 18 |
<button class="new_btn" onclick="modal.showModal()">New</button>
|
| 19 |
</div>
|
| 20 |
<div class="tasks">
|
| 21 |
+
|
| 22 |
+
@foreach ($tasks as $task)
|
| 23 |
+
<div class='task' onclick='showTask({{ $task->id }})'>
|
| 24 |
+
<span>{{ $task->title }}</span>
|
| 25 |
+
</div>
|
| 26 |
+
@endforeach
|
| 27 |
+
{{-- <div class='task' onclick='showTask(id)'>
|
| 28 |
<span>learn how fret works</span>
|
| 29 |
</div>
|
| 30 |
<div class='task'>
|
|
|
|
| 32 |
</div>
|
| 33 |
<div class='task'>
|
| 34 |
<span>learn guitar string names</span>
|
| 35 |
+
</div> --}}
|
| 36 |
|
| 37 |
</div>
|
| 38 |
</div>
|
| 39 |
</section>
|
| 40 |
<dialog id="modal">
|
| 41 |
<i onclick="modal.close()" class="fa-solid fa-xmark close_btn"></i>
|
| 42 |
+
<form class="container" method="POST" action="{{ route('dashboard.createtask', $skill->id) }}">
|
| 43 |
+
{{-- <form class="container" method="POST"> --}}
|
| 44 |
@csrf
|
| 45 |
<p class='title'>
|
| 46 |
New Task
|
|
|
|
| 61 |
<option value="app">Application</option>
|
| 62 |
</select>
|
| 63 |
<span class='error_msg'>
|
| 64 |
+
@error('task_type')
|
| 65 |
{{ $message }}
|
| 66 |
@enderror
|
| 67 |
</span>
|
|
|
|
| 69 |
<input type='submit' class='submit_btn' value='Add'>
|
| 70 |
</form>
|
| 71 |
</dialog>
|
| 72 |
+
|
| 73 |
+
<dialog id="task_modal">
|
| 74 |
+
<i onclick="task_modal.close()" class="fa-solid fa-xmark close_btn"></i>
|
| 75 |
+
<form class="container" method="POST" action="{{ route('dashboard.taskpracticed') }}">
|
| 76 |
+
@csrf
|
| 77 |
+
<input type='text' name="task_id" id="task_id" hidden>
|
| 78 |
+
<span class='title'>Title</span>
|
| 79 |
+
<span>Practice Count: <span class='count'>0</span></span>
|
| 80 |
+
<input class="practice_btn" type="submit" value="practiced">
|
| 81 |
+
</form>
|
| 82 |
+
</dialog>
|
| 83 |
+
|
| 84 |
+
<div id="error_container"></div>
|
| 85 |
+
|
| 86 |
+
<script src="{{ asset('js/dashboard/skill.js') }}"></script>
|
| 87 |
<script>
|
| 88 |
+
|
| 89 |
+
var taskdetail_url = "{{ route('dashboard.taskdetail', 1) }}";
|
| 90 |
+
taskdetail_url = taskdetail_url.split('/').slice(0, -1).join("/");
|
| 91 |
+
var taskdetail_url = "{{ route('dashboard.taskdetail', 1) }}";
|
| 92 |
+
taskdetail_url = taskdetail_url.split('/').slice(0, -1).join("/");
|
| 93 |
+
|
| 94 |
+
// task_modal.showModal();
|
| 95 |
+
@foreach($errors->all() as $error)
|
| 96 |
+
addError('{{ $error }}');
|
| 97 |
+
@endforeach
|
| 98 |
+
|
| 99 |
</script>
|
| 100 |
@endsection
|
routes/web.php
CHANGED
|
@@ -29,5 +29,8 @@
|
|
| 29 |
Route::get("/myskills",'myskills')->name("dashboard.myskills");
|
| 30 |
Route::post("/createskill",'createSkill')->name("dashboard.createskill");
|
| 31 |
Route::get("/skill/{id}",'skill')->name("dashboard.skill");
|
|
|
|
|
|
|
|
|
|
| 32 |
|
| 33 |
});
|
|
|
|
| 29 |
Route::get("/myskills",'myskills')->name("dashboard.myskills");
|
| 30 |
Route::post("/createskill",'createSkill')->name("dashboard.createskill");
|
| 31 |
Route::get("/skill/{id}",'skill')->name("dashboard.skill");
|
| 32 |
+
Route::post("/createtask/{skill_id}",'createTask')->name("dashboard.createtask");
|
| 33 |
+
Route::get("/taskdetail/{task_id}",'taskDetail')->name("dashboard.taskdetail");
|
| 34 |
+
Route::post("/taskpracticed",'taskPracticed')->name("dashboard.taskpracticed");
|
| 35 |
|
| 36 |
});
|