Skip to content

Commit

Permalink
profile, profile info, following
Browse files Browse the repository at this point in the history
  • Loading branch information
makssein committed Aug 26, 2023
1 parent 0199a4d commit 4d4196f
Show file tree
Hide file tree
Showing 20 changed files with 567 additions and 84 deletions.
38 changes: 38 additions & 0 deletions app/Http/Controllers/Web/Account/EditProfileController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace App\Http\Controllers\Web\Account;

use App\Http\Controllers\Controller;
use App\Http\Requests\Account\EditProfileRequest;
use App\Models\ProfileInfoModel;
use Illuminate\Http\Request;

class EditProfileController extends Controller {
public function edit(EditProfileRequest $request) {
$profile_info = ProfileInfoModel::updateOrCreate(
['user_id' => auth()->user()->id],
[
'bio' => $request->post('bio'),
'link' => $request->post('link')
]
);

auth()->user()->name = $request->name;
$save = auth()->user()->save();


if($profile_info && $save) {
return response()->json([
'status' => true,
'type' => 'success',
'message' => 'Данные успешно сохранены.'
]);
}

return response()->json([
'status' => false,
'type' => 'error',
'message' => 'Произошла ошибка. Попробуйте еще раз.'
]);
}
}
15 changes: 15 additions & 0 deletions app/Http/Controllers/Web/Account/ProfileController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace App\Http\Controllers\Web\Account;

use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;

class ProfileController extends Controller
{
public function render(User $user) {
$profile_info = $user->profileInfo;
return view('pages/account/profile', compact('user', 'profile_info'));
}
}
18 changes: 18 additions & 0 deletions app/Http/Controllers/Web/Follow/FollowsController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace App\Http\Controllers\Web\Follow;

use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;

class FollowsController extends Controller
{
public function follow(User $user) {
auth()->user()->toggleFollow($user);

return response()->json([
'status' => true
]);
}
}
8 changes: 7 additions & 1 deletion app/Http/Controllers/Web/Posts/PostsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@
use App\Http\Controllers\Controller;
use App\Http\Requests\Posts\CreateRequest;
use App\Models\PostsModel;
use App\Models\User;

class PostsController extends Controller {
public function get() {
public function feed() {
return auth()->user()->feed();
}

public function get($id) {
return User::find($id)->posts;
}


public function create(CreateRequest $request) {
$post = PostsModel::create([
'user_id' => auth()->id(),
Expand Down
59 changes: 59 additions & 0 deletions app/Http/Requests/Account/EditProfileRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

namespace App\Http\Requests\Account;

use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\Rules\Password;

class EditProfileRequest extends FormRequest
{
public function authorize() : bool {
return Auth::check();
}

public function rules(): array {
return [
'name' => 'required|min:3|string|max:255',
'bio' => 'nullable|string|min:5|max:255',
'link' => 'nullable|active_url'
];
}

public function attributes() : array {
return [
'name' => 'Имя',
'bio' => 'Описание',
'link' => 'Ссылка'
];
}

public function messages() : array {
return [
'required' => ":attribute является обязательным полем.",
'min' => ':attribute должен быть минимум :min символов.',
'string' => ':attribute должен быть строкой.',
'max' => ':attribute может быть максимум :max символов.',
'active_url' => ':attribute должна быть рабочей ссылкой.'
];
}

protected function failedValidation(Validator $validator) : void {
throw new HttpResponseException(response()->json([
'status' => false,
'type' => 'error',
'message' => $validator->errors()->first()
]));

}

public function failedAuthorization() : void {
throw new HttpResponseException(response()->json([
'status' => false,
'type' => 'error',
'message' => 'Вы не можете выполнить данное действие.'
]));
}
}
21 changes: 21 additions & 0 deletions app/Models/ProfileInfoModel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class ProfileInfoModel extends Model
{
protected $table = 'profile_info';

protected $primaryKey = 'user_id';

protected $fillable = [
'user_id',
'bio',
'link'
];


}
13 changes: 7 additions & 6 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Models;

use App\Traits\Followable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
Expand All @@ -10,7 +11,7 @@

class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
use HasApiTokens, HasFactory, Notifiable, Followable;

/**
* The attributes that are mass assignable.
Expand Down Expand Up @@ -53,14 +54,14 @@ public function feed() {
}

public function posts() {
return $this->hasMany(PostsModel::class)->with('user');
return $this->hasMany(PostsModel::class)->with('user')->latest();
}

public function follows() {
return $this->belongsToMany(User::class, 'follows', 'user_id', 'following_user_id');
public function profileLink() {
return route('profile.profile', $this->username);
}

public function follow(User $user) {
return $this->follows()->save($user);
public function profileInfo() {
return $this->hasOne(ProfileInfoModel::class);
}
}
38 changes: 38 additions & 0 deletions app/Traits/Followable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace App\Traits;

use App\Models\User;

trait Followable
{
public function follows()
{
return $this->belongsToMany(User::class, 'follows',
'user_id', 'following_user_id');
}

public function follow(User $user)
{
return $this->follows()->save($user);
}

public function unfollow(User $user)
{
return $this->follows()->detach($user);
}

public function toggleFollow(User $user) {
if($this->isFollowing($user)) {
return $this->unfollow($user);
}

return $this->follow($user);
}


public function isFollowing(User $user)
{
return $this->follows()->where('following_user_id', $user->id)->exists();
}
}
31 changes: 31 additions & 0 deletions database/migrations/2023_08_26_213732_profile_info_migration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('profile_info', function (Blueprint $table) {
$table->primary('user_id');
$table->string('bio')->nullable();
$table->string('link')->nullable();
$table->foreignId('user_id');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
//
}
};
46 changes: 44 additions & 2 deletions public/js/script.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,32 @@
$('#edit_profile_form').submit(function (e) {
e.preventDefault();

const _self = $(this);
const submit_button = _self.find(':submit');
submit_button.addClass('disabled');
submit_button.prop('disabled', true);

const url = _self.attr('action');
const data = new FormData(this);

axios.post(url, data)
.then(data => {
if(data.data.status) {
_self.closest('#edit_profile-modal').find('button[data-modal-hide]').trigger('click'); //закрытие модального окна
createToast({...data.data});
} else {
createToast({...data.data});
}
})
.catch(() => {
createToast({message: "Произошла ошибка. Попробуйте еще раз.", type: "error"});
})
.finally(() => {
submit_button.removeClass('disabled');
submit_button.prop('disabled', false);
});
});

$('#send_email_verification_form').submit(function (e) {
e.preventDefault();

Expand Down Expand Up @@ -125,9 +154,11 @@ function displayPost(data) {
' <img class="w-10 h-10 rounded-full mr-4" src="https://i.pravatar.cc/40" alt="avatar">\n' +
' </div>\n' +
' <div>\n' +
' <a href="/profile/'+ data.user.username +'">' +
' <h5 class="font-bold mb-2">\n' +
data.user.name +
' <span class="text-sm ml-1 font-normal text-gray-500">@'+ data.user.username +'</span>\n' +
' </a>' +
' <span class="text-sm font-medium text-gray-500">&#183;</span>\n' +
' <span class="text-sm font-normal text-gray-500">'+ post_date +'</span>\n' +
' </h5>\n' +
Expand All @@ -139,8 +170,19 @@ function displayPost(data) {
);
}

function getPosts() {
axios.get('/posts/get')
function getFeed() {
axios.get('/posts/feed')
.then(data => {
data.data.reverse();
data.data.forEach(post => {
displayPost(post);
});
})
.catch(() => createToast({message: "Произошла ошибка. Попробуйте еще раз.", type: "error"}))
}

function getPosts(user_id) {
axios.get('/posts/'+ user_id +'/get')
.then(data => {
data.data.reverse();
data.data.forEach(post => {
Expand Down
28 changes: 28 additions & 0 deletions resources/assets/js/editProfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
$('#edit_profile_form').submit(function (e) {
e.preventDefault();

const _self = $(this);
const submit_button = _self.find(':submit');
submit_button.addClass('disabled');
submit_button.prop('disabled', true);

const url = _self.attr('action');
const data = new FormData(this);

axios.post(url, data)
.then(data => {
if(data.data.status) {
_self.closest('#edit_profile-modal').find('button[data-modal-hide]').trigger('click'); //закрытие модального окна
createToast({...data.data});
} else {
createToast({...data.data});
}
})
.catch(() => {
createToast({message: "Произошла ошибка. Попробуйте еще раз.", type: "error"});
})
.finally(() => {
submit_button.removeClass('disabled');
submit_button.prop('disabled', false);
});
});
Loading

0 comments on commit 4d4196f

Please sign in to comment.