Add manual authentication, create, read, update task

This commit is contained in:
Thuan Bui
2025-03-06 17:00:09 +09:00
parent 154c37bce6
commit 67db6acefd
13 changed files with 325 additions and 20 deletions
+11
View File
@@ -8,4 +8,15 @@ use Illuminate\Database\Eloquent\Model;
class Task extends Model
{
use HasFactory;
protected $attributes = [
'completed' => false, // Set default value for completed
];
public function user() {
return $this->belongsTo(User::class);
}
public function category() {
return $this->belongsTo(Category::class);
}
}
+1 -1
View File
@@ -13,6 +13,6 @@ class TaskSeeder extends Seeder
*/
public function run(): void
{
Task::factory(100)->create();
Task::factory(20)->create();
}
}
+24
View File
@@ -0,0 +1,24 @@
<x-layout>
<x-slot:heading>Login Page</x-slot:heading>
<div>
<!-- Your content -->
<div class="w-full max-w-md p-8 mt-8 space-y-4 bg-white shadow-lg rounded-lg">
<h2 class="text-2xl font-bold text-center text-gray-700">Login</h2>
<form action="/login" method="POST" class="space-y-4">
@csrf
<div>
<label class="block text-sm font-medium text-gray-600">Email</label>
<input type="email" name="email" class="w-full p-2 mt-1 border rounded-md focus:ring focus:ring-blue-300" value="{{ old('email') }}" required>
<x-form-error name="email"></x-form-error>
</div>
<div>
<label class="block text-sm font-medium text-gray-600">Password</label>
<input type="password" name="password" class="w-full p-2 mt-1 border rounded-md focus:ring focus:ring-blue-300" required>
<x-form-error name="email"></x-form-error>
</div>
<button type="submit" class="w-full p-2 text-white bg-blue-500 rounded-md hover:bg-blue-600">Login</button>
</form>
</div>
</div>
</x-layout>
+34
View File
@@ -0,0 +1,34 @@
<x-layout>
<x-slot:heading>Register Page</x-slot:heading>
<div>
<!-- Your content -->
<div class="w-full max-w-md p-8 space-y-4 bg-white shadow-lg rounded-lg">
<form action="/register" method="POST" class="space-y-4">
@csrf
<div>
<label class="block text-sm font-medium text-gray-600">Full Name</label>
<input type="text" name="name" class="w-full p-2 mt-1 border rounded-md focus:ring focus:ring-blue-300" >
<x-form-error name="name"></x-form-error>
</div>
<div>
<label class="block text-sm font-medium text-gray-600">Email</label>
<input type="email" name="email" class="w-full p-name2 mt-1 border rounded-md focus:ring focus:ring-blue-300" >
<x-form-error name="email"></x-form-error>
</div>
<div>
<label class="block text-sm font-medium text-gray-600">Password</label>
<input type="password" name="password" class="w-full p-2 mt-1 border rounded-md focus:ring focus:ring-blue-300" >
<x-form-error name="password"></x-form-error>
</div>
<div>
<label class="block text-sm font-medium text-gray-600">Confirm Password</label>
<input type="password" name="password_confirmation" class="w-full p-2 mt-1 border rounded-md focus:ring focus:ring-blue-300" >
<x-form-error name="password_confirmation"></x-form-error>
</div>
<button type="submit" class="w-full p-2 text-white bg-blue-500 rounded-md hover:bg-blue-600">Register</button>
</form>
</div>
</div>
</x-layout>
@@ -0,0 +1 @@
<button type="submit" {{ $attributes->merge(['class' => 'rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-xs hover:bg-indigo-500 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600'])}}>{{ $slot }}</button>
@@ -0,0 +1,4 @@
@props(['name'])
@error($name)
<p class="text-xs text-red-500">{{ $message}}</p>
@enderror
+4 -10
View File
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Simple Tailwind Layout</title>
<title>{{ $heading }}</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="flex flex-col min-h-screen bg-gray-100">
@@ -11,17 +11,11 @@
<header class="bg-white shadow">
<div class="container mx-auto px-4 py-4 flex justify-between items-center">
<!-- Title on left -->
<h1 class="text-xl font-bold text-gray-800">MoveMate</h1>
<a href="/"><h1 class="text-xl font-bold text-gray-800">MoveMate</h1></a>
<!-- Navigation on right -->
<nav>
<ul class="flex space-x-6">
<li><a href="#" class="text-gray-600 hover:text-gray-900">Home</a></li>
<li><a href="#" class="text-gray-600 hover:text-gray-900">About</a></li>
<li><a href="#" class="text-gray-600 hover:text-gray-900">Services</a></li>
<li><a href="#" class="text-gray-600 hover:text-gray-900">Contact</a></li>
</ul>
</nav>
<x-nav />
</div>
</header>
@@ -0,0 +1 @@
<li><a {{ $attributes->merge(['class' => 'text-gray-600 hover:text-gray-900']) }}> {{ $slot }}</a></li>
+16
View File
@@ -0,0 +1,16 @@
<nav>
<ul class="flex space-x-6 items-center ">
@guest
<x-nav-link href="/login">Login</x-nav-link>
<x-nav-link href="/register">Register</x-nav-link>
@endguest
@auth
<x-nav-link type="button" href="/task/create">Create new task</x-nav-link>
<form method="POST" action="/logout">
@csrf
<x-form-button>Log Out</x-form-button>
</form>
@endauth
</ul>
</nav>
+44 -1
View File
@@ -1 +1,44 @@
Hello
<x-layout>
<x-slot:heading>Create New Task</x-slot:heading>
@if (session('success'))
<div class="bg-green-500 text-white p-3 rounded mb-4">
{{ session('success') }}
</div>
@endif
<form action="/task/create" method="POST" class="space-y-4">
@csrf
<div>
<label class="block text-sm font-medium text-gray-600">Task Name</label>
<input type="text" name="name" class="w-full p-2 mt-1 border rounded-md focus:ring focus:ring-blue-300" required>
<x-form-error name="name"></x-form-error>
</div>
<div>
<label class="block text-sm font-medium text-gray-600">Description</label>
<textarea name="description" class="w-full p-2 mt-1 border rounded-md focus:ring focus:ring-blue-300" rows="3" required></textarea>
<x-form-error name="description"></x-form-error>
</div>
<div>
<label class="block text-sm font-medium text-gray-600">Category</label>
<select name="category_id" class="w-full p-2 mt-1 border rounded-md focus:ring focus:ring-blue-300" required>
@foreach($categories as $category)
<option value="{{ $category->id }}">{{ $category->name }}</option>
@endforeach
</select>
<x-form-error name="category_id"></x-form-error>
</div>
<div>
<label class="block text-sm font-medium text-gray-600">Location</label>
<input type="text" name="location" class="w-full p-2 mt-1 border rounded-md focus:ring focus:ring-blue-300">
<x-form-error name="location"></x-form-error>
</div>
<div>
<label class="block text-sm font-medium text-gray-600">Estimated Time (hours)</label>
<input type="number" name="time_estimate" class="w-full p-2 mt-1 border rounded-md focus:ring focus:ring-blue-300" min="0" step="0.5" required>
<x-form-error name="time_estimate"></x-form-error>
</div>
<div class="flex flex-col items-center gap-y-6">
<button type="submit" class="w-full p-2 text-white bg-blue-500 rounded-md hover:bg-blue-600">Create Task</button>
<a href="/task/" class="text-sm font-semibold text-gray-900">Cancel</a>
</div>
</form>
</x-layout>
+48
View File
@@ -0,0 +1,48 @@
<x-layout>
<x-slot:heading>Update Task</x-slot:heading>
@if (session('success'))
<div class="bg-green-500 text-white p-3 rounded mb-4">
{{ session('success') }}
</div>
@endif
<form action="/task/{{ $task->id }}" method="POST" class="space-y-4">
@csrf
@method('PATCH')
<div>
<label class="block text-sm font-medium text-gray-600">Task Name</label>
<input value={{ $task->name }} type="text" name="name" class="w-full p-2 mt-1 border rounded-md focus:ring focus:ring-blue-300" required>
<x-form-error name="name"></x-form-error>
</div>
<div>
<label class="block text-sm font-medium text-gray-600">Description</label>
<textarea name="description" class="w-full p-2 mt-1 border rounded-md focus:ring focus:ring-blue-300" rows="3" required>{{ $task->description }}</textarea>
<x-form-error name="description"></x-form-error>
</div>
<div>
<label class="block text-sm font-medium text-gray-600">Category</label>
<select name="category_id" class="w-full p-2 mt-1 border rounded-md focus:ring focus:ring-blue-300" required>
@foreach($categories as $category)
<option value="{{ $category->id }}"
{{ $category->id == $task->category_id ? 'selected' : '' }}>
{{ $category->name }}
</option>
@endforeach
</select>
<x-form-error name="category_id"></x-form-error>
</div>
<div>
<label class="block text-sm font-medium text-gray-600">Location</label>
<input type="text" value="{{ $task->location }}" name="location" class="w-full p-2 mt-1 border rounded-md focus:ring focus:ring-blue-300">
<x-form-error name="location"></x-form-error>
</div>
<div>
<label class="block text-sm font-medium text-gray-600">Estimated Time (hours)</label>
<input type="number" value="{{ $task->time_estimate }}" name="time_estimate" class="w-full p-2 mt-1 border rounded-md focus:ring focus:ring-blue-300" min="0" step="0.5" required>
<x-form-error name="time_estimate"></x-form-error>
</div>
<div class="flex flex-col items-center gap-y-6">
<button type="submit" class="w-full p-2 text-white bg-blue-500 rounded-md hover:bg-blue-600">Update Task</button>
<a href="/jobs/{{ $task->id }}" type="button" class="text-sm font-semibold text-gray-900">Cancel</a>
</div>
</form>
</x-layout>
+17
View File
@@ -0,0 +1,17 @@
<x-layout>
<x-slot:heading>{{ $task->name }}</x-slot:heading>
<div>
<div class="text-lg mb-4"> {{ $task->description }}</div>
<div><strong>Where to go:</strong> {{ $task->location }}</div>
<div><strong>Time Estimate:</strong> {{ $task->time_estimate }} hour</div>
<div><strong>Category:</strong> {{ $task->category->name }}</div>
<div><strong>Owner:</strong> {{ $task->user->name }}</div>
</div>
<div class="mt-5">
<a href="/task/{{ $task->id }}/edit" class="text-sm text-blue-600 dark:text-blue-500 hover:underline">Edit</a>
</div>
</x-layout>
+120 -8
View File
@@ -1,24 +1,136 @@
<?php
use App\Models\Category;
use App\Models\Task;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;
use Illuminate\Validation\Rules\Password;
use Illuminate\Validation\ValidationException;
Route::get('/', function () {
return view('task.index');
});
Route::get('/task', function () {
$task = Task::latest()->Paginate(5);
$task = Task::latest('updated_at')->Paginate(20);
return view('task.index', [
'tasks' => $task
]);
});
Route::get('/task', function () {
$task = Task::latest('updated_at')->Paginate(20);
return view('task.index', [
'tasks' => $task
]);
});
Route::get('/task/create', function () {
return view('task.create');
$categories = Category::all();
return view('task.create', [
'categories' => $categories
]);
});
Route::post('/task/create', function () {
//dd(Auth::id());
$validatedAtts = request()->validate([
'name' => ['required'],
'description' => ['required'],
'category_id' => ['required'],
'location' => ['required'],
'time_estimate' => ['required'],
]);
$validatedAtts['user_id'] = Auth::id();
//dd($validatedAtts);
$task = Task::create(
$validatedAtts
);
return redirect()->route('task.create')->with('success', 'Task created successfully!');
})->name('task.create');
Route::get('/task/{id}', function ($id) {
$task = Task::find($id);
return view('task.show', [
'task' => $task
]);
});
Route::get('/task/{id}/edit', function ($id) {
$task = Task::find($id);
$categories = Category::all();
return view('task.edit', [
'task' => $task,
'categories' => $categories
]);
});
Route::patch('/task/{id}', function ($id) {
$task = Task::find($id);
$validatedAtts = request()->validate([
'name' => ['required'],
'description' => ['required'],
'category_id' => ['required'],
'location' => ['required'],
'time_estimate' => ['required'],
]);
//dd($task);
$task->update($validatedAtts);
return redirect('/task/'.$task->id);
});
Route::get('/login', function () {
return view('auth.login');
});
Route::post('/login', function () {
$validatedAtts = request()->validate([
'email' => ['required'],
'password' => ['required']
]);
//dd($validatedAtts);
// Attemp
if (! Auth::attempt($validatedAtts)) {
throw ValidationException::withMessages([
'email' => 'The information does not match'
]);
};
// regenerate the session token
request()->session()->regenerate();
//redirect
return redirect('/task');
});
Route::get('/register', function () {
return view('auth.register');
});
Route::post('/register', function () {
//validate
$validatedAtts = request()->validate([
'name' => ['required'],
'email' => ['required'],
'password' => ['required', Password::min(2), 'confirmed']
]);
$user = User::create($validatedAtts);
Auth::login($user);
});
Route::post('/logout', function() {
Auth::logout();
return redirect('/');
});