Complete profile management functionality

This commit is contained in:
Christopher C. Wells 2021-04-22 11:29:41 -07:00
parent adc63d975c
commit 78c3095036
6 changed files with 102 additions and 20 deletions

View File

@ -22,7 +22,9 @@ trait UpdatesUser
else {
unset($input['password']);
}
$input['admin'] = $input['admin'] ?? false;
// Maintain the existing value if it is not on the form.
$input['admin'] = $input['admin'] ?? ($user->exists && $user->admin);
$user->fill($input)->save();

File diff suppressed because one or more lines are too long

View File

@ -27,10 +27,13 @@
<x-slot name="content">
<div class="space-y-2">
<x-dropdown-link :href="route('goals.index')">Goals</x-dropdown-link>
<x-dropdown-link :href="route('profiles.show', Auth::user())">My Profile</x-dropdown-link>
<x-dropdown-link :href="route('goals.index')">My Goals</x-dropdown-link>
@can('administer', \App\Models\User::class)
<x-dropdown-link :href="route('users.index')">Users</x-dropdown-link>
<hr />
<x-dropdown-link :href="route('users.index')">Manage Users</x-dropdown-link>
@endcan
<hr />
<form method="POST" action="{{ route('logout') }}" x-data>
@csrf
<x-dropdown-link :href="route('logout')" @click.prevent="$el.closest('form').submit();">Logout</x-dropdown-link>

View File

@ -1,9 +1,24 @@
<x-app-layout>
<x-slot name="title">Profile</x-slot>
@php($title = ($user->id === Auth::user()->id ? 'My Profile': "{$user->name}'s Profile"))
<x-slot name="title">{{ $title }}</x-slot>
<x-slot name="header">
<div class="flex justify-between items-center">
<h1 class="font-semibold text-2xl text-gray-800 leading-tight">Profile</h1>
<h1 class="font-semibold text-2xl text-gray-800 leading-tight">{{ $title }}</h1>
@can('editProfile', $user)
<x-button-link.green href="{{ route('profiles.edit', $user) }}" class="text-sm">
Edit Profile
</x-button-link.green>
@endcan
</div>
</x-slot>
{{ $user->name }}
@if($user->hasMedia())
<div class="inline-block">
<a href="{{ $user->getFirstMedia()->getFullUrl() }}" target="_blank">
{{ $user->getFirstMedia()('icon') }}
</a>
</div>
<div class="mt-2 text-gray-500">
{{ $user->name }}
</div>
@endif
</x-app-layout>

View File

@ -10,12 +10,12 @@
<div class="flex flex-col space-y-4">
<div class="flex flex-col space-y-4 md:flex-row md:space-x-4 md:space-y-0">
<!-- Username -->
<div class="flex-auto">
<div class="flex-auto space-y-1">
<x-inputs.label for="username" value="Username"/>
<x-inputs.input name="username"
type="text"
class="block mt-1 w-full"
class="block w-full"
autocapitalize="none"
:value="old('username', $user->username)"
:hasError="$errors->has('username')"
@ -23,12 +23,12 @@
</div>
<!-- Name -->
<div class="flex-auto">
<div class="flex-auto space-y-1">
<x-inputs.label for="name" value="Display name"/>
<x-inputs.input name="name"
type="text"
class="block mt-1 w-full"
class="block w-full"
:value="old('name', $user->name)"/>
</div>
@ -36,36 +36,37 @@
<div class="flex flex-col space-y-4 md:flex-row md:space-x-4 md:space-y-0">
<!-- Password -->
<div class="flex-auto">
<div class="flex-auto space-y-1">
<x-inputs.label for="password" value="Password"/>
<x-inputs.input name="password"
type="password"
class="block mt-1 w-full"
class="block w-full"
:hasError="$errors->has('password')"
:required="!$user->exists"/>
</div>
<!-- Password confirm -->
<div class="flex-auto">
<div class="flex-auto space-y-1">
<x-inputs.label for="password_confirmation" value="Confirm Password"/>
<x-inputs.input name="password_confirmation"
type="password"
class="block mt-1 w-full"
class="block w-full"
:hasError="$errors->has('password')"
:required="!$user->exists"/>
</div>
</div>
<!-- Admin -->
<div class="space-x-2">
<div class="space-y-1">
<x-inputs.label for="admin" value="Site Admin" class="inline-block"/>
<x-inputs.input name="admin"
type="checkbox"
value="1"
:checked="old('admin', $user->admin)" />
<x-inputs.select name="admin"
class="block"
:options="[['value' => 0, 'label' => 'No'], ['value' => 1, 'label' => 'Yes']]"
:selectedValue="old('admin', $user->admin)">
</x-inputs.select>
</div>
<!-- Image -->

View File

@ -0,0 +1,61 @@
<?php
namespace Tests\Feature\Http\Controllers;
use App\Http\Controllers\ProfileController;
use App\Models\User;
use Tests\LoggedInTestCase;
class ProfileControllerTest extends LoggedInTestCase
{
/**
* Test view own profile.
*/
public function testCanViewOwnProfile(): void
{
$view_url = action([ProfileController::class, 'show'], ['user' => $this->user]);
$response = $this->get($view_url);
$response->assertOk();
$response->assertViewHas('user', $this->user);
}
/**
* Test view other user profile.
*/
public function testCanViewOtherUserProfile(): void
{
$user = User::factory()->createOne();
$view_url = action([ProfileController::class, 'show'], ['user' => $user]);
$response = $this->get($view_url);
$response->assertOk();
$response->assertViewHas('user', $user);
}
/**
* Test view own profile.
*/
public function testCanEditOwnProfile(): void
{
$edit_url = action([ProfileController::class, 'edit'], ['user' => $this->user]);
$response = $this->get($edit_url);
$response->assertOk();
$new_user = User::factory()->make();
$put_url = action([ProfileController::class, 'update'], ['user' => $this->user]);
$response = $this->put($put_url, $new_user->toArray());
$response->assertSessionHasNoErrors();
}
/**
* Test view own profile.
*/
public function testCanNotEditOtherUserProfile(): void
{
$user = User::factory()->createOne();
$edit_url = action([ProfileController::class, 'edit'], ['user' => $user]);
$response = $this->get($edit_url);
$response->assertForbidden();
}
}