parent
e147d24365
commit
6854c7a9f8
@ -29,11 +29,11 @@ class UserAvatarGenerator
|
||||
protected function generate(User $user): SVG
|
||||
{
|
||||
return $this->generator->rounded()
|
||||
->background($this->getColor($user->name))
|
||||
->background($this->getColor($user->fullName))
|
||||
->color("#F4F8FD")
|
||||
->smooth()
|
||||
->fontSize(0.33)
|
||||
->generateSvg($user->name);
|
||||
->generateSvg($user->fullName);
|
||||
}
|
||||
|
||||
protected function getColor(string $name): string
|
||||
|
@ -20,7 +20,8 @@ class UserController extends Controller
|
||||
$users = User::query()
|
||||
->withTrashed()
|
||||
->search($request->query("search"))
|
||||
->latest()
|
||||
->orderBy("last_name")
|
||||
->orderBy("first_name")
|
||||
->paginate()
|
||||
->withQueryString();
|
||||
|
||||
|
@ -14,8 +14,14 @@ class VacationLimitController extends Controller
|
||||
{
|
||||
public function edit(): Response
|
||||
{
|
||||
$limits = VacationLimit::query()
|
||||
->with("user")
|
||||
->orderByUserField("last_name")
|
||||
->orderByUserField("first_name")
|
||||
->get();
|
||||
|
||||
return inertia("VacationLimits", [
|
||||
"limits" => VacationLimitResource::collection(VacationLimit::query()->with("user")->get()),
|
||||
"limits" => VacationLimitResource::collection($limits),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,8 @@ class UserRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
"name" => ["required", "min:3", "max: 150"],
|
||||
"firstName" => ["required", "min:3", "max:80"],
|
||||
"lastName" => ["required", "min:3", "max:80"],
|
||||
"email" => ["required", "email", Rule::unique("users", "email")->ignore($this->user)],
|
||||
"employmentForm" => ["required", new Enum(EmploymentForm::class)],
|
||||
"employmentDate" => ["required", "date"],
|
||||
@ -24,7 +25,8 @@ class UserRequest extends FormRequest
|
||||
public function data(): array
|
||||
{
|
||||
return [
|
||||
"name" => $this->get("name"),
|
||||
"first_name" => $this->get("firstName"),
|
||||
"last_name" => $this->get("lastName"),
|
||||
"email" => $this->get("email"),
|
||||
"employment_form" => $this->get("employmentForm"),
|
||||
"employment_date" => $this->get("employmentDate"),
|
||||
|
@ -14,7 +14,8 @@ class UserFormDataResource extends JsonResource
|
||||
{
|
||||
return [
|
||||
"id" => $this->id,
|
||||
"name" => $this->name,
|
||||
"firstName" => $this->first_name,
|
||||
"lastName" => $this->last_name,
|
||||
"email" => $this->email,
|
||||
"employmentForm" => $this->employment_form,
|
||||
"employmentDate" => $this->employment_date,
|
||||
|
@ -14,7 +14,7 @@ class UserResource extends JsonResource
|
||||
{
|
||||
return [
|
||||
"id" => $this->id,
|
||||
"name" => $this->name,
|
||||
"name" => $this->fullName,
|
||||
"email" => $this->email,
|
||||
"role" => "Human Resources Manager",
|
||||
"avatar" => asset($this->avatar),
|
||||
|
@ -16,7 +16,8 @@ use Toby\Enums\EmploymentForm;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property string $first_name
|
||||
* @property string $last_name
|
||||
* @property string $email
|
||||
* @property string $avatar
|
||||
* @property EmploymentForm $employment_form
|
||||
@ -29,13 +30,7 @@ class User extends Authenticatable
|
||||
use Notifiable;
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable = [
|
||||
"name",
|
||||
"email",
|
||||
"avatar",
|
||||
"employment_form",
|
||||
"employment_date",
|
||||
];
|
||||
protected $guarded = [];
|
||||
|
||||
protected $casts = [
|
||||
"employment_form" => EmploymentForm::class,
|
||||
@ -58,7 +53,8 @@ class User extends Authenticatable
|
||||
}
|
||||
|
||||
return $query
|
||||
->where("name", "LIKE", "%{$text}%")
|
||||
->where("first_name", "LIKE", "%{$text}%")
|
||||
->orWhere("last_name", "LIKE", "%{$text}%")
|
||||
->orWhere("email", "LIKE", "%{$text}%");
|
||||
}
|
||||
|
||||
@ -68,4 +64,9 @@ class User extends Authenticatable
|
||||
|
||||
$this->save();
|
||||
}
|
||||
|
||||
public function getFullNameAttribute(): string
|
||||
{
|
||||
return "{$this->first_name} {$this->last_name}";
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Toby\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
@ -34,4 +35,11 @@ class VacationLimit extends Model
|
||||
{
|
||||
return $this->belongsTo(YearPeriod::class);
|
||||
}
|
||||
|
||||
public function scopeOrderByUserField(Builder $query, string $field): Builder
|
||||
{
|
||||
$userQuery = User::query()->select($field)->whereColumn("vacation_limits.user_id", "users.id");
|
||||
|
||||
return $query->orderBy($userQuery);
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ class UserObserver
|
||||
|
||||
public function updating(User $user): void
|
||||
{
|
||||
if ($user->isDirty("name")) {
|
||||
if ($user->isDirty(["first_name", "last_name"])) {
|
||||
Storage::delete($user->avatar);
|
||||
$user->avatar = $this->generator->generateFor($user);
|
||||
}
|
||||
|
@ -13,7 +13,8 @@ class UserFactory extends Factory
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
"name" => "{$this->faker->firstName} {$this->faker->lastName}",
|
||||
"first_name" => $this->faker->firstName(),
|
||||
"last_name" => $this->faker->lastName(),
|
||||
"email" => $this->faker->unique()->safeEmail(),
|
||||
"employment_form" => $this->faker->randomElement(EmploymentForm::cases()),
|
||||
"employment_date" => $this->faker->dateTimeBetween("2020-10-27"),
|
||||
|
@ -17,7 +17,6 @@ class VacationLimitFactory extends Factory
|
||||
return [
|
||||
"user_id" => User::factory(),
|
||||
"year_period_id" => YearPeriod::factory(),
|
||||
"has_vacation" => $hasVacation,
|
||||
"days" => $hasVacation ? $this->faker->numberBetween(20, 26) : null,
|
||||
];
|
||||
}
|
||||
|
@ -11,7 +11,8 @@ return new class() extends Migration {
|
||||
{
|
||||
Schema::create("users", function (Blueprint $table): void {
|
||||
$table->id();
|
||||
$table->string("name");
|
||||
$table->string("first_name");
|
||||
$table->string("last_name");
|
||||
$table->string("email")->unique();
|
||||
$table->string("avatar")->nullable();
|
||||
$table->string("employment_form");
|
||||
|
@ -15,24 +15,47 @@
|
||||
>
|
||||
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
|
||||
<label
|
||||
for="name"
|
||||
for="firstName"
|
||||
class="block text-sm font-medium text-gray-700 sm:mt-px"
|
||||
>
|
||||
Imię i nazwisko
|
||||
Imię
|
||||
</label>
|
||||
<div class="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<input
|
||||
id="name"
|
||||
v-model="form.name"
|
||||
id="firstName"
|
||||
v-model="form.firstName"
|
||||
type="text"
|
||||
class="block w-full max-w-lg shadow-sm rounded-md sm:text-sm"
|
||||
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.name, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.name }"
|
||||
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.firstName, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.firstName }"
|
||||
>
|
||||
<p
|
||||
v-if="form.errors.name"
|
||||
v-if="form.errors.firstName"
|
||||
class="mt-2 text-sm text-red-600"
|
||||
>
|
||||
{{ form.errors.name }}
|
||||
{{ form.errors.firstName }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
|
||||
<label
|
||||
for="lastName"
|
||||
class="block text-sm font-medium text-gray-700 sm:mt-px"
|
||||
>
|
||||
Nazwisko
|
||||
</label>
|
||||
<div class="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<input
|
||||
id="lastName"
|
||||
v-model="form.lastName"
|
||||
type="text"
|
||||
class="block w-full max-w-lg shadow-sm rounded-md sm:text-sm"
|
||||
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.lastName, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.lastName }"
|
||||
>
|
||||
<p
|
||||
v-if="form.errors.lastName"
|
||||
class="mt-2 text-sm text-red-600"
|
||||
>
|
||||
{{ form.errors.lastName }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -184,7 +207,8 @@ export default {
|
||||
},
|
||||
setup(props) {
|
||||
const form = useForm({
|
||||
name: null,
|
||||
firstName: null,
|
||||
lastName: null,
|
||||
email: null,
|
||||
employmentForm: props.employmentForms[0],
|
||||
employmentDate: new Date(),
|
||||
|
@ -15,24 +15,47 @@
|
||||
>
|
||||
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
|
||||
<label
|
||||
for="name"
|
||||
for="firstName"
|
||||
class="block text-sm font-medium text-gray-700 sm:mt-px"
|
||||
>
|
||||
Imię i nazwisko
|
||||
Imię
|
||||
</label>
|
||||
<div class="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<input
|
||||
id="name"
|
||||
v-model="form.name"
|
||||
id="firstName"
|
||||
v-model="form.firstName"
|
||||
type="text"
|
||||
class="block w-full max-w-lg shadow-sm rounded-md sm:text-sm"
|
||||
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.name, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.name }"
|
||||
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.firstName, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.firstName }"
|
||||
>
|
||||
<p
|
||||
v-if="form.errors.name"
|
||||
v-if="form.errors.firstName"
|
||||
class="mt-2 text-sm text-red-600"
|
||||
>
|
||||
{{ form.errors.name }}
|
||||
{{ form.errors.firstName }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
|
||||
<label
|
||||
for="lastName"
|
||||
class="block text-sm font-medium text-gray-700 sm:mt-px"
|
||||
>
|
||||
Nazwisko
|
||||
</label>
|
||||
<div class="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<input
|
||||
id="lastName"
|
||||
v-model="form.lastName"
|
||||
type="text"
|
||||
class="block w-full max-w-lg shadow-sm rounded-md sm:text-sm"
|
||||
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.lastName, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.lastName }"
|
||||
>
|
||||
<p
|
||||
v-if="form.errors.lastName"
|
||||
class="mt-2 text-sm text-red-600"
|
||||
>
|
||||
{{ form.errors.lastName }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -188,7 +211,8 @@ export default {
|
||||
},
|
||||
setup(props) {
|
||||
const form = useForm({
|
||||
name: props.user.name,
|
||||
firstName: props.user.firstName,
|
||||
lastName: props.user.lastName,
|
||||
email: props.user.email,
|
||||
employmentForm: props.employmentForms.find(form => form.value === props.user.employmentForm),
|
||||
employmentDate: new Date(props.user.employmentDate),
|
||||
|
@ -200,7 +200,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<div
|
||||
v-if="users.data.length"
|
||||
v-if="users.data.length && users.meta.last_page !== 1"
|
||||
class="bg-white px-4 py-3 flex items-center justify-between border-t border-gray-200 sm:px-6 rounded-b-lg"
|
||||
>
|
||||
<div class="flex-1 flex justify-between sm:hidden">
|
||||
|
@ -34,22 +34,27 @@ class UserTest extends FeatureTestCase
|
||||
public function testAdminCanSearchUsersList(): void
|
||||
{
|
||||
User::factory([
|
||||
"name" => "Test User1",
|
||||
"first_name" => "Test",
|
||||
"last_name" => "User1",
|
||||
])->create();
|
||||
User::factory([
|
||||
"name" => "Test User2",
|
||||
"first_name" => "Test",
|
||||
"last_name" => "User2",
|
||||
])->create();
|
||||
User::factory([
|
||||
"name" => "Test User3",
|
||||
"first_name" => "Test",
|
||||
"last_name" => "User3",
|
||||
])->create();
|
||||
$admin = User::factory([
|
||||
"name" => "John Doe",
|
||||
"first_name" => "John",
|
||||
"last_name" => "Doe",
|
||||
])->create();
|
||||
|
||||
$this->assertDatabaseCount("users", 4);
|
||||
|
||||
$this->actingAs($admin)
|
||||
->get("/users?search=test")
|
||||
->assertOk()
|
||||
->assertInertia(
|
||||
fn(Assert $page) => $page
|
||||
->component("Users/Index")
|
||||
@ -80,7 +85,8 @@ class UserTest extends FeatureTestCase
|
||||
|
||||
$this->actingAs($admin)
|
||||
->post("/users", [
|
||||
"name" => "John Doe",
|
||||
"firstName" => "John",
|
||||
"lastName" => "Doe",
|
||||
"email" => "john.doe@example.com",
|
||||
"employmentForm" => EmploymentForm::B2B_CONTRACT->value,
|
||||
"employmentDate" => Carbon::now()->toDateTimeString(),
|
||||
@ -88,7 +94,8 @@ class UserTest extends FeatureTestCase
|
||||
->assertSessionHasNoErrors();
|
||||
|
||||
$this->assertDatabaseHas("users", [
|
||||
"name" => "John Doe",
|
||||
"first_name" => "John",
|
||||
"last_name" => "Doe",
|
||||
"email" => "john.doe@example.com",
|
||||
"employment_form" => EmploymentForm::B2B_CONTRACT->value,
|
||||
"employment_date" => Carbon::now()->toDateTimeString(),
|
||||
@ -103,7 +110,8 @@ class UserTest extends FeatureTestCase
|
||||
Carbon::setTestNow();
|
||||
|
||||
$this->assertDatabaseHas("users", [
|
||||
"name" => $user->name,
|
||||
"first_name" => $user->first_name,
|
||||
"last_name" => $user->last_name,
|
||||
"email" => $user->email,
|
||||
"employment_form" => $user->employment_form->value,
|
||||
"employment_date" => $user->employment_date->toDateTimeString(),
|
||||
@ -111,7 +119,8 @@ class UserTest extends FeatureTestCase
|
||||
|
||||
$this->actingAs($admin)
|
||||
->put("/users/{$user->id}", [
|
||||
"name" => "John Doe",
|
||||
"firstName" => "John",
|
||||
"lastName" => "Doe",
|
||||
"email" => "john.doe@example.com",
|
||||
"employmentForm" => EmploymentForm::B2B_CONTRACT->value,
|
||||
"employmentDate" => Carbon::now()->toDateTimeString(),
|
||||
@ -119,7 +128,8 @@ class UserTest extends FeatureTestCase
|
||||
->assertSessionHasNoErrors();
|
||||
|
||||
$this->assertDatabaseHas("users", [
|
||||
"name" => "John Doe",
|
||||
"first_name" => "John",
|
||||
"last_name" => "Doe",
|
||||
"email" => "john.doe@example.com",
|
||||
"employment_form" => EmploymentForm::B2B_CONTRACT->value,
|
||||
"employment_date" => Carbon::now()->toDateTimeString(),
|
||||
|
@ -49,7 +49,8 @@ class AvatarTest extends TestCase
|
||||
Storage::assertExists($oldAvatar);
|
||||
|
||||
$user->update([
|
||||
"name" => "John Doe",
|
||||
"first_name" => "John",
|
||||
"last_name" => "Doe",
|
||||
]);
|
||||
|
||||
Storage::assertMissing($oldAvatar);
|
||||
|
Loading…
x
Reference in New Issue
Block a user