Spaces:
Sleeping
Sleeping
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 |
});
|