friendship system

This commit is contained in:
Conkley 2022-07-06 20:49:41 +10:00
parent 307b9adbe9
commit 19269f856c
17 changed files with 670 additions and 153 deletions

View File

@ -0,0 +1,112 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Multicaret\Acquaintances\Traits\Friendable;
class FriendController extends Controller
{
use Friendable;
public function friends(Request $request)
{
/*
use Illuminate\Support\Str;
if ($request->has('q')) {
$userFriends = Auth::user()->getFriends();
foreach ($userFriends as $users) {
if (Str::contains($users->name, $request->get('q'))) {
$user = collect($users);
dd($user);
}
}
}*/
/* ADD THIS: search feature */
$user = Auth::user()->getFriends($perPage = 10);
return view('pages.friends')->with('userFriends', $user);
}
public function requests()
{
$user = Auth::user()->getFriendRequests();
return view('pages.requests')->with('userRequests', $user);
}
public function handle($id, Request $request)
{
$action = $request->input('action');
if ($action == 'accept') {
$this->accept($id);
} else {
$this->decline($id);
}
return redirect()->route('requests');
}
public function accept($id): void
{
$user = Auth::user();
$recipient = User::find($id);
if (!$user->hasFriendRequestFrom($recipient)) {
abort(404);
}
$user->acceptFriendRequest($recipient);
}
public function decline($id): void
{
$user = Auth::user();
$recipient = User::find($id);
if (!$user->hasFriendRequestFrom($recipient)) {
abort(404);
}
$user->denyFriendRequest($recipient);
}
public function add($id)
{
$user = Auth::user();
$recipient = User::find($id);
if (!$recipient || $recipient->id == $user->id) {
abort(404);
}
if ($user->hasSentFriendRequestTo($recipient) || $user->hasFriendRequestFrom($recipient)) {
abort(404);
}
$user->befriend($recipient);
return redirect()->back();
}
public function remove($id)
{
$user = Auth::user();
$recipient = User::find($id);
if (!$recipient || $recipient->id == $user->id) {
abort(404);
}
if (!$user->isFriendWith($recipient)) {
abort(404);
}
$user->unfriend($recipient);
return redirect()->back();
}
}

View File

@ -3,6 +3,7 @@
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class HomeController extends Controller
{
@ -31,6 +32,8 @@ class HomeController extends Controller
public function home()
{
return view('home');
$friends = Auth::user()->getFriends($perPage = 3);
return view('home')->with('friends', $friends);
}
}

View File

@ -28,6 +28,7 @@ class PageController extends Controller
{
$user = User::find($id);
$badges = DB::table('badges')->get();
$friends = $user->getFriends($perPage = 3);
if (!$user) {
abort(404);
@ -35,12 +36,30 @@ class PageController extends Controller
$data = [
'user' => $user,
'badges' => $badges
'badges' => $badges,
'friends' => $friends
];
return view('pages.profile')->with('data', $data);
}
public function profile_friends($id)
{
$user = User::find($id);
$friends = $user->getFriends($perPage = 10);
if (!$user) {
abort(404);
}
$data = [
'user' => $user,
'friends' => $friends
];
return view('pages.profile_friends')->with('data', $data);
}
public function users(Request $request)
{
if ($request->has('q')) {
@ -56,9 +75,4 @@ class PageController extends Controller
{
return view('misc.settings');
}
public function friends()
{
return view('pages.friends');
}
}

View File

@ -8,10 +8,11 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Multicaret\Acquaintances\Traits\Friendable;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
use HasApiTokens, HasFactory, Notifiable, Friendable;
/**
* The attributes that are mass assignable.

View File

@ -12,6 +12,7 @@
"laravel/sanctum": "^2.11",
"laravel/tinker": "^2.5",
"laravel/ui": "^3.4",
"multicaret/laravel-acquaintances": "^3.5",
"webpatser/laravel-uuid": "^4.0"
},
"require-dev": {

72
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "25ae453eae609a277c5bbd141f21342f",
"content-hash": "5b427c2301ce3db3e2dbf83c41ddf6ed",
"packages": [
{
"name": "asm89/stack-cors",
@ -1825,6 +1825,76 @@
],
"time": "2022-06-09T08:59:12+00:00"
},
{
"name": "multicaret/laravel-acquaintances",
"version": "v3.5.6",
"source": {
"type": "git",
"url": "https://github.com/multicaret/laravel-acquaintances.git",
"reference": "702e446fec8d3ac69aa88243cef247d7602989e4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/multicaret/laravel-acquaintances/zipball/702e446fec8d3ac69aa88243cef247d7602989e4",
"reference": "702e446fec8d3ac69aa88243cef247d7602989e4",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"require-dev": {
"codeclimate/php-test-reporter": "^0.3.2",
"doctrine/dbal": "^2.5",
"fzaninotto/faker": "~1.4",
"laravel/laravel": "5.*",
"mockery/mockery": "1.0.x-dev",
"phpunit/phpunit": "5.*"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Multicaret\\Acquaintances\\AcquaintancesServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Multicaret\\Acquaintances\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mohamed Kawsara",
"email": "mkwsra@gmail.com"
}
],
"description": "This light package, with no dependencies, gives Eloquent models the ability to manage friendships (with groups). And interactions such as: Likes, favorites, votes, subscribe, follow, ..etc. And it includes advanced rating system.",
"keywords": [
"Followers",
"Rate",
"Rating",
"eloquent",
"followships",
"friend-system",
"friends",
"friendships",
"interactions",
"laravel",
"like",
"social-media",
"wish-list"
],
"support": {
"issues": "https://github.com/multicaret/laravel-acquaintances/issues",
"source": "https://github.com/multicaret/laravel-acquaintances/tree/v3.5.6"
},
"time": "2022-02-18T05:49:20+00:00"
},
{
"name": "nesbot/carbon",
"version": "2.58.0",

87
config/acquaintances.php Normal file
View File

@ -0,0 +1,87 @@
<?php
return [
/**
* Load migrations from package migrations,
* If you published the migration files, please set to `false`.
*/
'migrations' => false,
/*
* Models Related.
*/
'model_namespace' => (int) app()->version() <= 7 ? 'App' : 'App\Models',
'models' => [
/*
* Model name of User model
*/
'user' => 'User',
/*
* Model name of Interaction Relation model
*/
'interaction_relation' => \Multicaret\Acquaintances\Models\InteractionRelation::class,
/*
* Model name of Interaction Relation model
*/
'friendship' => \Multicaret\Acquaintances\Models\Friendship::class,
/*
* Model name of Interaction Relation model
*/
'friendship_groups' => \Multicaret\Acquaintances\Models\FriendFriendshipGroups::class,
],
'tables' => [
/*
* Table name of interactions relations.
*/
'interactions' => 'interactions',
/*
* user foreign key column name within interactions table.
*/
'interactions_user_id_fk_column_name' => 'user_id',
/*
* user foreign key column type within interactions table.
*/
'interactions_user_id_fk_column_type' => 'unsignedBigInteger',
/*
* Table name of friendships relations.
*/
'friendships' => 'friendships',
/*
* Table name of friendship Groups relations.
*/
'friendship_groups' => 'friendship_groups',
],
'rating' => [
'defaults' => [
'amount' => 5,
/*
* Default type here is 'general', as longs as you have one criteria of rating a model
* you can ignore this setting.
* It will be the default type of rating of null is provided, if you wish to tweak this type name
* use the value below as you wish.
*
*/
'type' => 'general',
],
'types' => [
/* Add any other type that your website/application have here,
* the following added rating types are for demonstration purposes only.
* There is no effect on deleting them nor adding to them, however, its a good practice
* to not hard code your rating types, hence, please use this simple array
*/
'delivery-time',
'quality',
'communication',
'commitment',
]
],
'friendships_groups' => [
'acquaintances' => 0,
'close_friends' => 1,
'family' => 2
],
];

View File

@ -0,0 +1,27 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateAcquaintancesFriendshipTable extends Migration
{
public function up()
{
Schema::create(config('acquaintances.tables.friendships'), function (Blueprint $table) {
$table->id();
$table->morphs('sender');
$table->morphs('recipient');
$table->string('status')->default('pending')->comment('pending/accepted/denied/blocked/');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists(config('acquaintances.tables.friendships'));
}
}

View File

@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
/**
* Class CreateFriendshipsGroupsTable
*/
class CreateAcquaintancesFriendshipsGroupsTable extends Migration
{
public function up()
{
Schema::create(config('acquaintances.tables.friendship_groups'), function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('friendship_id')->unsigned();
$table->morphs('friend');
$table->integer('group_id')->unsigned();
$table->foreign('friendship_id')
->references('id')
->on(config('acquaintances.tables.friendships'))
->onDelete('cascade');
$table->unique(['friendship_id', 'friend_id', 'friend_type', 'group_id'], 'unique');
});
}
public function down()
{
Schema::dropIfExists(config('acquaintances.tables.friendship_groups'));
}
}

View File

@ -0,0 +1,48 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateAcquaintancesInteractionsTable extends Migration
{
/**
* Run the migrations.
*/
public function up()
{
Schema::create(config('acquaintances.tables.interactions', 'interactions'), function (Blueprint $table) {
$table->id();
$userModel = config('auth.providers.users.model');
$userModel = (new $userModel);
$userIdFkType = config('acquaintances.tables.interactions_user_id_fk_column_type');
$table->{$userIdFkType}('user_id')->index();
$table->morphs('subject');
$table->string('relation')->default('follow')->comment('follow/like/subscribe/favorite/upvote/downvote');
$table->double('relation_value')->nullable();
$table->string('relation_type')->nullable();
$table->timestamps();
$table->foreign('user_id')
->references($userModel->getKeyName())
->on($userModel->getTable())
->onUpdate('cascade')
->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*/
public function down()
{
Schema::table(config('acquaintances.tables.interactions', 'interactions'), function ($table) {
$table->dropForeign(config('acquaintances.tables.interactions', 'interactions').'_user_id_foreign');
});
Schema::drop(config('acquaintances.tables.interactions', 'interactions'));
}
}

View File

@ -3,7 +3,7 @@
<title>Home - {{ env('APP_NAME') }}</title>
@endsection
@section('titlediscord')
<meta content="Home - {{env('APP_NAME')}}" property="og:title" />
<meta content="Home - {{ env('APP_NAME') }}" property="og:title" />
@endsection
@section('descdiscord')
<meta content="ARCHBLOX is a work in progress revival." property="og:description" />
@ -22,8 +22,8 @@
<div id="FeedContainer">
<div class="FeedContainerBox" id="FeedContainerBox1">
<div class="FeedContainerBoxImageContainer" id="FeedContainerBox1ImageContainer">
<a href="#"><img alt="Profile Image" src="{{ asset('img/reviewpending.png') }}" width="60px"
height="100%"></a>
<a href="#"><img alt="Profile Image" src="{{ asset('img/reviewpending.png') }}"
width="60px" height="100%"></a>
</div>
<div class="FeedContainerBoxTextContainer" id="FeedContainerBox1TextContainer">
<a href="#" id="FeedContainerBox1Username">skeuomorphism hater</a>
@ -33,8 +33,8 @@
</div>
<div class="FeedContainerBox" id="FeedContainerBox1">
<div class="FeedContainerBoxImageContainer" id="FeedContainerBox1ImageContainer">
<a href="#"><img alt="Profile Image" src="{{ asset('img/reviewpending.png') }}" width="60px"
height="100%"></a>
<a href="#"><img alt="Profile Image" src="{{ asset('img/reviewpending.png') }}"
width="60px" height="100%"></a>
</div>
<div class="FeedContainerBoxTextContainer" id="FeedContainerBox1TextContainer">
<a href="#" id="FeedContainerBox1Username">Thomas</a>
@ -44,8 +44,8 @@
</div>
<div class="FeedContainerBox" id="FeedContainerBox1">
<div class="FeedContainerBoxImageContainer" id="FeedContainerBox1ImageContainer">
<a href="#"><img alt="Profile Image" src="{{ asset('img/reviewpending.png') }}" width="60px"
height="100%"></a>
<a href="#"><img alt="Profile Image" src="{{ asset('img/reviewpending.png') }}"
width="60px" height="100%"></a>
</div>
<div class="FeedContainerBoxTextContainer" id="FeedContainerBox1TextContainer">
<a href="#" id="FeedContainerBox1Username">skeuomorphism hater</a>
@ -55,8 +55,8 @@
</div>
<div class="FeedContainerBox" id="FeedContainerBox1">
<div class="FeedContainerBoxImageContainer" id="FeedContainerBox1ImageContainer">
<a href="#"><img alt="Profile Image" src="{{ asset('img/reviewpending.png') }}" width="60px"
height="100%"></a>
<a href="#"><img alt="Profile Image" src="{{ asset('img/reviewpending.png') }}"
width="60px" height="100%"></a>
</div>
<div class="FeedContainerBoxTextContainer" id="FeedContainerBox1TextContainer">
<a href="#" id="FeedContainerBox1Username">Thomas</a>
@ -67,8 +67,8 @@
</div>
<div class="FeedContainerBox" id="FeedContainerBox1">
<div class="FeedContainerBoxImageContainer" id="FeedContainerBox1ImageContainer">
<a href="#"><img alt="Profile Image" src="{{ asset('img/reviewpending.png') }}" width="60px"
height="100%"></a>
<a href="#"><img alt="Profile Image" src="{{ asset('img/reviewpending.png') }}"
width="60px" height="100%"></a>
</div>
<div class="FeedContainerBoxTextContainer" id="FeedContainerBox1TextContainer">
<a href="#" id="FeedContainerBox1Username">the night guard from five nights at freddy</a>
@ -78,8 +78,8 @@
</div>
<div class="FeedContainerBox" id="FeedContainerBox1">
<div class="FeedContainerBoxImageContainer" id="FeedContainerBox1ImageContainer">
<a href="#"><img alt="Profile Image" src="{{ asset('img/reviewpending.png') }}" width="60px"
height="100%"></a>
<a href="#"><img alt="Profile Image" src="{{ asset('img/reviewpending.png') }}"
width="60px" height="100%"></a>
</div>
<div class="FeedContainerBoxTextContainer" id="FeedContainerBox1TextContainer">
<a href="#" id="FeedContainerBox1Username">Thomas</a>
@ -90,11 +90,34 @@
</div>
</div>
<div id="gamesframe">
<h2>Friends (0)</h2>
<div class="content_special" style="justify-content: center;">
<h2>Friends ({{ Auth::user()->getFriendsCount() }})</h2>
@if (Auth::user()->getFriendsCount() > 0)
<a href="{{ route('friends') }}" style="margin-left: 5px"> <button class="bluebutton"
style="margin-top: 5px">View
All</button></a>
@endif
</div>
<br>
<br>
<div class="friendslist">
<p>You don't have any friends yet!</p>
@if (Auth::user()->getFriendsCount() > 0)
<div id="profilefriendcontainer" class="content_special"
style="flex-wrap: nowrap;justify-content: space-evenly;flex-direction: row;display: inline-flex;align-content: center;align-items: center;">
@foreach ($friends as $friend)
<div class="profilefriend">
<a href="{{ route('profile', $friend->id) }}"><img alt="Profile Image"
src="{{ asset('img/reviewpending.png') }}" width="150px" height="110px"></a>
<br>
<a href="{{ route('profile', $friend->id) }}"
id="FeedContainerBox1Username">{{ $friend->name }}</a>
</div>
@endforeach
</div>
</div>
@else
<p>You don't have any friends yet!</p>
@endif
<br>
<h2>Recently Played</h2>
<br>

View File

@ -57,7 +57,7 @@
</div>
<div class="smallnav">
<div class="smallnavbarbuttoncontainer">
<a class="smallnavbarbutton" href="{{ route('friends') }}">Friends</a>
<a class="smallnavbarbutton" href="{{ route('friends') }}">Friends @if (!Auth::guest() && count(Auth::user()->getFriendRequests())) <span class="warningtext">({{ count(Auth::user()->getFriendRequests()) }})</span> @endif</a>
<a class="smallnavbarbutton" href="#">Avatar</a>
<a class="smallnavbarbutton" href="#">Transactions</a>
<a class="smallnavbarbutton" href="{{ route('users') }}">Users</a>

View File

@ -1,67 +1,48 @@
@extends('layouts.app')
@section('title')
<title>Friends - {{ env('APP_NAME') }}</title>
@endsection
@section('titlediscord')
<meta content="Friends - {{env('APP_NAME')}}" property="og:title" />
@endsection
@section('descdiscord')
<meta content="ARCHBLOX is a work in progress revival." property="og:description" />
<title>Friends - {{ env('APP_NAME') }}</title>
@endsection
@section('content')
<h1 id="usernameframe">Friends</h1>
<a href="#" class="tab_selected">All Friends</a>
<a href="#" class="tab">Pending Requests</a>
<br>
<br>
<form method="GET" action="{{ route('users') }}">
<p><input type="text" id="q" name="q" placeholder="Enter a Username..." value="{{ request()->q }}">
<button class="greybutton" type="submit">Search</button>
</p>
</form>
<br>
<div class="content_special" id="FriendsContainer" style="flex-wrap: wrap;">
<div class="FriendsContainerBox" id="FriendsContainerBox1">
<div id="FriendsContainerBox1ImageContainer">
<a href=""><img alt="Profile Image" src="{{ asset('img/reviewpending.png') }}" width="60px"
height="100%"></a>
</div>
<div id="FriendsContainerBox1TextContainer">
<a href="" id="FeedContainerBox1Username">BallsGamer123</a>
<p>"I'm new to ARCHBLOX!"</p>
<strong id="onlinestatus" class="onlinestatus_website">Website</strong>
<br>
<button class="redbutton">Unfriend</button>
</div>
<h1 id="usernameframe">Friends</h1>
<a href="#" class="tab_selected">All Friends</a>
<a href="{{ route('requests') }}" class="tab">Pending Requests ({{ count(Auth::user()->getFriendRequests()) }})</a>
<br>
<!--
<form method="GET" action="{{ route('friends') }}">
<p><input type="text" id="q" name="q" placeholder="Enter a Username..." value="{{ request()->q }}">
<button class="greybutton" type="submit">Search</button>
</p>
</form>-->
<br>
<div class="content_special" id="FriendsContainer" style="flex-wrap: wrap;">
@foreach ($userFriends as $user)
<div class="FriendsContainerBox" id="FriendsContainerBox1">
<div id="FriendsContainerBox1ImageContainer">
<a href="{{ route('profile', $user->id) }}"><img alt="Profile Image"
src="{{ asset('img/reviewpending.png') }}" width="60px" height="100%"></a>
</div>
<div id="FriendsContainerBox1TextContainer">
<a href="{{ route('profile', $user->id) }}" id="FeedContainerBox1Username">{{ $user->name }}</a>
<p>"I'm new to ARCHBLOX!"</p>
@if (Cache::has('is_online_' . $user->id))
<strong id="onlinestatus" class="onlinestatus_website">Website</strong>
@else
<strong id="onlinestatus" class="onlinestatus_offline">Offline - Last Online
{{ Carbon\Carbon::parse($user->last_seen)->diffForHumans() }}</strong>
@endif
<br>
<form action="{{ route('friend_remove', $user->id) }}" method="POST" style="display:inline-block">
@csrf
<button class="redbutton" type="submit">Unfriend</button>
</form>
</div>
</div>
@endforeach
@if (!count($userFriends))
<p>You haven't made friends with anyone yet.</p>
@endif
{{ $userFriends->links() }}
</div>
<div class="FriendsContainerBox" id="FriendsContainerBox1">
<div id="FriendsContainerBox1ImageContainer">
<a href=""><img alt="Profile Image" src="{{ asset('img/reviewpending.png') }}" width="60px"
height="100%"></a>
</div>
<div id="FriendsContainerBox1TextContainer">
<a href="" id="FeedContainerBox1Username">BallsGamer123</a>
<p>"I'm new to ARCHBLOX!"</p>
<strong id="onlinestatus" class="onlinestatus_website">Website</strong>
<br>
<button class="redbutton">Unfriend</button>
</div>
</div>
<div class="FriendsContainerBox" id="FriendsContainerBox1">
<div id="FriendsContainerBox1ImageContainer">
<a href=""><img alt="Profile Image" src="{{ asset('img/reviewpending.png') }}" width="60px"
height="100%"></a>
</div>
<div id="FriendsContainerBox1TextContainer">
<a href="" id="FeedContainerBox1Username">BallsGamer123</a>
<p>"I'm new to ARCHBLOX!"</p>
<strong id="onlinestatus" class="onlinestatus_website">Website</strong>
<br>
<button class="redbutton">Unfriend</button>
</div>
</div>
</div>
<br>
@endsection
<br>
@endsection

View File

@ -1,87 +1,107 @@
@extends('layouts.app')
@section('title')
<title>{{ $data['user']->name }} - {{ env('APP_NAME') }}</title>
<title>{{ $data['user']->name }} - {{ env('APP_NAME') }}</title>
@endsection
@section('titlediscord')
<meta content="{{ $data['user']->name }} - {{env('APP_NAME')}}" property="og:title" />
<meta content="{{ $data['user']->name }} - {{ env('APP_NAME') }}" property="og:title" />
@endsection
@section('descdiscord')
<meta content="{{ $data['user']->blurb }} | ARCHBLOX is a work in progress revival." property="og:description" />
@endsection
@section('content')
<div id="profiletopcontainer">
<h1 id="usernameframe">{{ $data['user']->name }}</h1>
@if (Cache::has('is_online_' . $data['user']->id))
<strong id="onlinestatus" class="onlinestatus_website">Website</strong>
@else
<strong id="onlinestatus" class="onlinestatus_offline">Offline - Last Online
{{ Carbon\Carbon::parse($data['user']->last_seen)->diffForHumans() }}</strong>
@endif
<br>
<a href="#"><button class="bluebutton">Add Friend</button></a>
<a href="#"><button class="greybutton">Message</button></a>
</div>
<div class="content_special">
<div id="profileleftcontainer">
<p id="status">"I'm new to ARCHBLOX!"</p>
<img alt="profile image" src="{{ asset('img/reviewpending.png') }}" width="75%">
<p id="bio">{{ $data['user']->blurb }}</p>
<div id="profiletopcontainer">
<h1 id="usernameframe">{{ $data['user']->name }}</h1>
@if (Cache::has('is_online_' . $data['user']->id))
<strong id="onlinestatus" class="onlinestatus_website">Website</strong>
@else
<strong id="onlinestatus" class="onlinestatus_offline">Offline - Last Online
{{ Carbon\Carbon::parse($data['user']->last_seen)->diffForHumans() }}</strong>
@endif
<br>
<div id="stats">
<h3>Joined: {{ $data['user']->created_at->format('d/m/Y') }}</h3>
<h3>Place Visits: 0</h3>
</div>
<br>
<h2>Role</h2>
<div style="white-space:nowrap">
@foreach ($data['badges'] as $badge)
@foreach ($data['user']->badges as $user_badge)
@if ($badge->id == $user_badge)
<div style="width:120px;display:inline-block">
<img src="/img/badges/{{ $badge->id }}.png" width="75px" height="75px" />
<h3>{{ $badge->title }}</h3>
</div>
@if (!Auth::guest() && Auth::id() != $data['user']->id)
@if (Auth::user()->hasSentFriendRequestTo($data['user']))
<button class="bluebutton" type="submit" disabled>Pending...</button>
@elseif (Auth::user()->hasFriendRequestFrom($data['user']))
<form action="{{ route('friend_handle', $data['user']->id) }}" method="POST">
@csrf
<button class="greenbutton" name="action" type="submit" value="accept">Accept</button>
<button class="redbutton" name="action" type="submit" value="decline">Decline</button>
</form>
@elseif (Auth::user()->isFriendWith($data['user']))
<form action="{{ route('friend_remove', $data['user']->id) }}" method="POST"
style="display:inline-block">
@csrf
<button class="redbutton" type="submit">Unfriend</button>
</form>
@else
<form action="{{ route('friend_add', $data['user']->id) }}" method="POST" style="display:inline-block">
@csrf
<button class="bluebutton" type="submit">Add Friend</button>
</form>
@endif
@endforeach
@endforeach
</div>
<br>
<h2>Badges</h2>
<p>This user has not collected any badges yet!</p>
<a href="#"><button class="greybutton">Message</button></a>
@endif
</div>
<div id="profilerightcontainer">
<div class="content_special" style="justify-content: center;">
<h2>Games </h2>
<a href="#" style="margin-left: 5px"> <button class="bluebutton" style="margin-top: 5px">View
All</button></a>
</div>
<p>This user hasn't made any games yet!</p>
<br>
<div class="content_special" style="justify-content: center;">
<h2>Friends (1337)</h2>
<a href="{{ route('friends') }}" style="margin-left: 5px"> <button class="bluebutton"
style="margin-top: 5px">View All</button></a>
</div>
<div id="profilefriendcontainer" class="content_special" style="flex-wrap: nowrap;justify-content: space-evenly;flex-direction: row;display: inline-flex;align-content: center;align-items: center;">
<div class="profilefriend">
<a href="#"><img alt="Profile Image" src="{{ asset('img/reviewpending.png') }}" width="90%" height="100%"></a>
<div class="content_special">
<div id="profileleftcontainer">
<p id="status">"I'm new to ARCHBLOX!"</p>
<img alt="profile image" src="{{ asset('img/reviewpending.png') }}" width="75%">
<p id="bio">{{ $data['user']->blurb }}</p>
<br>
<a href="#" id="FeedContainerBox1Username">BallsGamer123</a>
<div id="stats">
<h3>Joined: {{ $data['user']->created_at->format('d/m/Y') }}</h3>
<h3>Place Visits: 0</h3>
</div>
<div class="profilefriend">
<a href="#"><img alt="Profile Image" src="{{ asset('img/reviewpending.png') }}" width="90%" height="100%"></a>
<br>
<a href="#" id="FeedContainerBox1Username">BallsGamer123</a>
<h2>Role</h2>
<div style="white-space:nowrap">
@foreach ($data['badges'] as $badge)
@foreach ($data['user']->badges as $user_badge)
@if ($badge->id == $user_badge)
<div style="width:120px;display:inline-block">
<img src="/img/badges/{{ $badge->id }}.png" width="75px" height="75px" />
<h3>{{ $badge->title }}</h3>
</div>
@endif
@endforeach
@endforeach
</div>
<div class="profilefriend">
<a href="#"><img alt="Profile Image" src="{{ asset('img/reviewpending.png') }}" width="90%" height="100%"></a>
<br>
<a href="#" id="FeedContainerBox1Username">BallsGamer123</a>
</div>
<h2>Badges</h2>
<p>This user has not collected any badges yet!</p>
</div>
<div id="profilerightcontainer">
<div class="content_special" style="justify-content: center;">
<h2>Games </h2>
<a href="#" style="margin-left: 5px"> <button class="bluebutton" style="margin-top: 5px">View
All</button></a>
</div>
<p>This user hasn't made any games yet!</p>
<br>
<div class="content_special" style="justify-content: center;">
<h2>Friends ({{ $data['user']->getFriendsCount() }})</h2>
@if ($data['user']->getFriendsCount() > 0)
<a href="{{ route('profile_friends', $data['user']->id) }}" style="margin-left: 5px"> <button class="bluebutton"
style="margin-top: 5px">View All</button></a>
</div>
<div id="profilefriendcontainer" class="content_special"
style="flex-wrap: nowrap;justify-content: space-evenly;flex-direction: row;display: inline-flex;align-content: center;align-items: center;">
@foreach ($data['friends'] as $friend)
<div class="profilefriend">
<a href="{{ route('profile', $friend->id) }}"><img alt="Profile Image"
src="{{ asset('img/reviewpending.png') }}" width="150px" height="110px"></a>
<br>
<a href="{{ route('profile', $friend->id) }}"
id="FeedContainerBox1Username">{{ $friend->name }}</a>
</div>
@endforeach
</div>
@else
</div>
<p>This user hasn't made friends with anyone!</p>
@endif
</div>
</div>
<br>
@endsection
</div>
<br>
@endsection

View File

@ -0,0 +1,42 @@
@extends('layouts.app')
@section('title')
<title>{{ $data['user']->name }}'s Friends - {{ env('APP_NAME') }}</title>
@endsection
@section('content')
<h1 id="usernameframe">{{ $data['user']->name }}'s Friends ({{ $data['user']->getFriendsCount() }})</h1>
<br>
<div class="content_special" id="FriendsContainer" style="flex-wrap: wrap;">
@foreach ($data['friends'] as $friend)
<div class="FriendsContainerBox" id="FriendsContainerBox1">
<div id="FriendsContainerBox1ImageContainer">
<a href="{{ route('profile', $friend->id) }}"><img alt="Profile Image"
src="{{ asset('img/reviewpending.png') }}" width="60px" height="100%"></a>
</div>
<div id="FriendsContainerBox1TextContainer">
<a href="{{ route('profile', $friend->id) }}" id="FeedContainerBox1Username">{{ $friend->name }}</a>
<p>"I'm new to ARCHBLOX!"</p>
@if (Cache::has('is_online_' . $friend->id))
<strong id="onlinestatus" class="onlinestatus_website">Website</strong>
@else
<strong id="onlinestatus" class="onlinestatus_offline">Offline - Last Online
{{ Carbon\Carbon::parse($friend->last_seen)->diffForHumans() }}</strong>
@endif
<br>
@if (Auth::id() == $data['user']->id)
<form action="{{ route('friend_remove', $friend->id) }}" method="POST"
style="display:inline-block">
@csrf
<button class="redbutton" type="submit">Unfriend</button>
</form>
@endif
</div>
</div>
@endforeach
@if (!$data['user']->getFriendsCount())
<p>You haven't made friends with anyone yet.</p>
@endif
{{ $data['friends']->links() }}
</div>
<br>
@endsection

View File

@ -0,0 +1,43 @@
@extends('layouts.app')
@section('title')
<title>Friend Requests - {{ env('APP_NAME') }}</title>
@endsection
@section('content')
<h1 id="usernameframe">Friends</h1>
<a href="{{ route('friends') }}" class="tab">All Friends</a>
<a href="#" class="tab_selected">Pending Requests ({{ count(Auth::user()->getFriendRequests()) }})</a>
<br>
<br>
<div class="content_special" id="FriendsContainer" style="flex-wrap: wrap;">
@foreach ($userRequests as $userReq)
@php $user = App\Models\User::find($userReq->sender_id) @endphp
<div class="FriendsContainerBox" id="FriendsContainerBox1">
<div id="FriendsContainerBox1ImageContainer">
<a href="{{ route('profile', $user->id) }}"><img alt="Profile Image"
src="{{ asset('img/reviewpending.png') }}" width="60px" height="100%"></a>
</div>
<div id="FriendsContainerBox1TextContainer">
<a href="{{ route('profile', $user->id) }}" id="FeedContainerBox1Username">{{ $user->name }}</a>
<p>"I'm new to ARCHBLOX!"</p>
@if (Cache::has('is_online_' . $user->id))
<strong id="onlinestatus" class="onlinestatus_website">Website</strong>
@else
<strong id="onlinestatus" class="onlinestatus_offline">Offline - Last Online
{{ Carbon\Carbon::parse($user->last_seen)->diffForHumans() }}</strong>
@endif
<br>
<form action="{{ route('friend_handle', $user->id) }}" method="POST">
@csrf
<button class="greenbutton" name="action" type="submit" value="accept">Accept</button>
<button class="redbutton" name="action" type="submit" value="decline">Decline</button>
</form>
</div>
</div>
@endforeach
@if (!count($userRequests))
<p>You have no pending friend requests.</p>
@endif
</div>
<br>
@endsection

View File

@ -21,6 +21,7 @@ Route::get('/', [App\Http\Controllers\HomeController::class, 'index'])->name('in
Route::get('/privacy', [App\Http\Controllers\PageController::class, 'privacy'])->name('privacy');
Route::get('/tos', [App\Http\Controllers\PageController::class, 'tos'])->name('tos');
Route::get('/user/{id}', [App\Http\Controllers\PageController::class, 'profile'])->name('profile');
Route::get('/user/{id}/friends', [App\Http\Controllers\PageController::class, 'profile_friends'])->name('profile_friends');
// Must be logged in
Route::middleware(['auth'])->group(function () {
@ -30,7 +31,13 @@ Route::middleware(['auth'])->group(function () {
Route::get('/my/settings', [App\Http\Controllers\PageController::class, 'settings'])->name('settings');
Route::get('/my/invites', [App\Http\Controllers\KeyController::class, 'index'])->name('key_index');
Route::post('/my/invites', [App\Http\Controllers\KeyController::class, 'create'])->name('key_create');
Route::get('/my/friends', [App\Http\Controllers\PageController::class, 'friends'])->name('friends');
// Friendship system routes
Route::get('/my/friends', [App\Http\Controllers\FriendController::class, 'friends'])->name('friends');
Route::get('/my/friends/requests', [App\Http\Controllers\FriendController::class, 'requests'])->name('requests');
Route::post('/my/friends/requests/{id}', [App\Http\Controllers\FriendController::class, 'handle'])->name('friend_handle');
Route::post('/friends/add/{id}', [App\Http\Controllers\FriendController::class, 'add'])->name('friend_add');
Route::post('/friends/remove/{id}', [App\Http\Controllers\FriendController::class, 'remove'])->name('friend_remove');
});
// Admin only