Rework user page, more page concepts.
- Added page concept for games. - User page now mostly resembles what Roblox's user profile page looked like back in 2016. - Added biography for users.
This commit is contained in:
parent
550fafeee5
commit
6c482f5a22
Binary file not shown.
|
|
@ -91,15 +91,12 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
return $this->created_at->isoFormat('ll');
|
||||
}
|
||||
|
||||
// XlXi: Returns a class name like text-success or
|
||||
// gt-status-studio to show next to the
|
||||
// user's name.
|
||||
public function getOnlineClass()
|
||||
// XlXi: TODO: Replace this with detailed presence
|
||||
// like what game the user is in or
|
||||
// what place they're editing.
|
||||
public function isOnline()
|
||||
{
|
||||
if($this->last_seen >= Carbon::now()->subMinutes(2))
|
||||
return 'text-success';
|
||||
|
||||
return 'text-muted';
|
||||
return ($this->last_seen >= Carbon::now()->subMinutes(2));
|
||||
}
|
||||
|
||||
public function _hasRolesetInternal($roleName)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ return new class extends Migration
|
|||
$table->rememberToken();
|
||||
$table->unsignedBigInteger('banId')->nullable();
|
||||
|
||||
$table->string('biography')->nullable();
|
||||
|
||||
$table->unsignedBigInteger('tokens')->default(0);
|
||||
$table->dateTime('next_reward')->useCurrent();
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
Graphictoria 5 (https://gtoria.net)
|
||||
Copyright © XlXi 2022
|
||||
*/
|
||||
|
||||
import { Component, createRef } from 'react';
|
||||
|
||||
import classNames from 'classnames/bind';
|
||||
|
||||
import axios from 'axios';
|
||||
|
||||
import Twemoji from 'react-twemoji';
|
||||
|
||||
import { buildGenericApiUrl } from '../util/HTTP.js';
|
||||
import ProgressiveImage from './ProgressiveImage';
|
||||
import Loader from './Loader';
|
||||
|
||||
axios.defaults.withCredentials = true;
|
||||
|
||||
function commaSeparate(num) {
|
||||
let str = num.toString().split('.');
|
||||
str[0] = str[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
return str.join('.');
|
||||
}
|
||||
|
||||
class GameItemCard extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
hovered: false
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<a
|
||||
className="graphictoria-item-card"
|
||||
href="#"
|
||||
onMouseEnter={() => this.setState({hovered: true})}
|
||||
onMouseLeave={() => this.setState({hovered: false})}
|
||||
>
|
||||
<span className="card m-2">
|
||||
<ProgressiveImage
|
||||
src={ buildGenericApiUrl('www', 'images/busy/game.png') }
|
||||
placeholderImg={ buildGenericApiUrl('www', 'images/busy/game.png') }
|
||||
alt="Game todo"
|
||||
className='img-fluid'
|
||||
/>
|
||||
<div className="p-2">
|
||||
<p>Todo</p>
|
||||
<p className="text-muted small">{commaSeparate(1337)} Playing</p>
|
||||
<div className="d-flex mt-1">
|
||||
<i className={classNames({
|
||||
'fa-solid': true,
|
||||
'fa-thumbs-up': true,
|
||||
'text-success': this.state.hovered
|
||||
})}></i>
|
||||
<div className={classNames({
|
||||
'my-auto': true,
|
||||
'mx-1': true,
|
||||
'graphictoria-vote-bar': true,
|
||||
'rounded-1': true,
|
||||
'border': true,
|
||||
'border-light': true,
|
||||
'position-relative': true,
|
||||
'flex-fill': true,
|
||||
'bg-secondary': !this.state.hovered,
|
||||
'bg-danger': this.state.hovered
|
||||
})}>
|
||||
<div className={classNames({
|
||||
'rounded-1': true,
|
||||
'position-absolute': true,
|
||||
'bg-dark': !this.state.hovered,
|
||||
'bg-success': this.state.hovered,
|
||||
})}
|
||||
style={{width: '80%', height: '8px'}}></div>
|
||||
</div>
|
||||
<i className={classNames({
|
||||
'fa-solid': true,
|
||||
'fa-thumbs-down': true,
|
||||
'text-danger': this.state.hovered
|
||||
})}></i>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
{
|
||||
this.state.hovered ?
|
||||
<span className="graphictoria-item-details">
|
||||
<div className="card px-2">
|
||||
<hr className="m-0" />
|
||||
<p className="text-truncate my-1">
|
||||
<span className="text-muted">By </span><a href="#" className="text-decoration-none fw-normal">Todo</a>
|
||||
</p>
|
||||
</div>
|
||||
</span>
|
||||
:
|
||||
null
|
||||
}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Games extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="container-lg my-2 d-flex flex-column">
|
||||
<h4 className="my-auto">Games</h4>
|
||||
<Loader />
|
||||
<GameItemCard />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Games;
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
Graphictoria 5 (https://gtoria.net)
|
||||
Copyright © XlXi 2022
|
||||
*/
|
||||
|
||||
import $ from 'jquery';
|
||||
|
||||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
|
||||
import Games from '../components/Games';
|
||||
|
||||
const gamesId = 'gt-games-main';
|
||||
|
||||
$(document).ready(function() {
|
||||
if (document.getElementById(gamesId)) {
|
||||
render(<Games />, document.getElementById(gamesId));
|
||||
}
|
||||
});
|
||||
|
|
@ -1345,3 +1345,29 @@ p {
|
|||
-webkit-animation-fill-mode: both;
|
||||
-webkit-animation-name: dropdownEase;
|
||||
}
|
||||
|
||||
// Voting
|
||||
.graphictoria-vote-bar {
|
||||
// border
|
||||
html.gtoria-dark & {
|
||||
border-color: $gray-700;
|
||||
}
|
||||
html.gtoria-light & {
|
||||
border-color: $border-color;
|
||||
}
|
||||
|
||||
// rounded-1
|
||||
border-radius: 0.2rem;
|
||||
|
||||
// bg-secondary
|
||||
background-color: $secondary;
|
||||
|
||||
// my-auto and mx-1
|
||||
margin: auto 0.25rem auto 0.25rem;
|
||||
|
||||
// flex-fill
|
||||
flex: 1 1 auto;
|
||||
|
||||
position: relative;
|
||||
height: 10px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
@section('title', 'Games')
|
||||
|
||||
@section('page-specific')
|
||||
<script src="{{ mix('js/Games.js') }}"></script>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div id="gt-games-main" class="container-lg my-2 d-flex flex-column">
|
||||
<h4 class="my-auto">Games</h4>
|
||||
|
|
|
|||
|
|
@ -8,39 +8,31 @@
|
|||
|
||||
@section('content')
|
||||
<div class="container-lg my-2">
|
||||
<h4>Hello, {{ Auth::user()->username }}!</h4>
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<h4>Hello, {{ Auth::user()->username }}!</h4>
|
||||
<div class="card text-center">
|
||||
<img src="{{ asset('/images/testing/avatar.png') }}" class="img-fluid gt-charimg" />
|
||||
</div>
|
||||
|
||||
<x-MiniCard class="mt-3 d-none d-md-flex">
|
||||
<x-slot name="title">
|
||||
Blog
|
||||
</x-slot>
|
||||
<x-slot name="body">
|
||||
<ul class="text-center list-unstyled mb-1">
|
||||
<li class="pb-2"><a href="#" class="text-decoration-none fw-normal"><i class="fa-solid fa-circle-right"></i> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</a></li>
|
||||
<li class="pb-2"><a href="#" class="text-decoration-none fw-normal"><i class="fa-solid fa-circle-right"></i> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</a></li>
|
||||
<li class="pb-2"><a href="#" class="text-decoration-none fw-normal"><i class="fa-solid fa-circle-right"></i> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</a></li>
|
||||
</ul>
|
||||
<div class="text-left px-2">
|
||||
<a href="https://blog.gtoria.net" class="text-decoration-none fw-normal" target="_blank">More <i class="fa-solid fa-caret-right"></i></a>
|
||||
</div>
|
||||
</x-slot>
|
||||
</x-MiniCard>
|
||||
<h4 class="mt-3">Blog</h4>
|
||||
<div class="card p-2">
|
||||
<ul class="text-center list-unstyled mb-0">
|
||||
<li class="pb-2"><a href="#" class="text-decoration-none fw-normal"><i class="fa-solid fa-circle-right"></i> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</a></li>
|
||||
<li class="pb-2"><a href="#" class="text-decoration-none fw-normal"><i class="fa-solid fa-circle-right"></i> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</a></li>
|
||||
<li class="pb-2"><a href="#" class="text-decoration-none fw-normal"><i class="fa-solid fa-circle-right"></i> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</a></li>
|
||||
</ul>
|
||||
<div class="text-left">
|
||||
<a href="https://blog.gtoria.net" class="text-decoration-none fw-normal" target="_blank">More <i class="fa-solid fa-caret-right"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-9 mt-3 mt-md-0">
|
||||
<x-MiniCard class="d-none d-md-flex mb-3">
|
||||
<x-slot name="title">
|
||||
Recently Played
|
||||
</x-slot>
|
||||
<x-slot name="body">
|
||||
Content here.
|
||||
</x-slot>
|
||||
</x-MiniCard>
|
||||
<div class="col-md-9">
|
||||
<h4 class="mt-3 mt-md-0">Recently Played</h4>
|
||||
<div class="card p-2 mb-3">
|
||||
Content here.
|
||||
</div>
|
||||
|
||||
<div id="gt-dash-feed"></div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
{{-- XlXi: References lol --}}
|
||||
{{-- XlXi: https://cubash.com/@Icseon --}}
|
||||
{{-- XlXi: https://youtu.be/nouY1ugddcI?t=583 --}}
|
||||
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', $title)
|
||||
|
||||
@section('page-specific')
|
||||
@endsection
|
||||
|
||||
@section('quick-admin')
|
||||
<li class="nav-item">
|
||||
{{-- TODO: XlXi: Make this use route() --}}
|
||||
|
|
@ -17,113 +18,100 @@
|
|||
@endsection
|
||||
|
||||
@section('content')
|
||||
<style>
|
||||
.graphictoria-user-profile-buttons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.graphictoria-user-profile-buttons > .btn:not(:last-child) {
|
||||
/* me-1 */
|
||||
margin-right: 0.25rem!important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container-lg my-2">
|
||||
<div class="graphictoria-smaller-page">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card p-2 text-center">
|
||||
<h5 class="mb-0"><span class="{{ $user->getOnlineClass() }}">●</span> {{ $user->username }}</h5>
|
||||
@if(false)
|
||||
{{-- TODO: XlXi: this lol --}}
|
||||
<p class="text-success">[ Playing: Among Us ]</p>
|
||||
@endif
|
||||
<img src="{{ asset('/images/testing/avatar.png') }}" width="300px" height="300px" class="img-fluid mx-auto gt-charimg" />
|
||||
<p class="text-muted pb-2">TODO: user description</p>
|
||||
@auth
|
||||
<div class="graphictoria-user-profile-buttons">
|
||||
<button class="btn btn-secondary">Add Friend</button>
|
||||
<button class="btn btn-secondary">Send Message</button>
|
||||
<button class="btn btn-secondary">Block</button>
|
||||
</div>
|
||||
@endauth
|
||||
<hr class="mb-1" />
|
||||
<div class="row text-center">
|
||||
<div class="col-4">
|
||||
<p class="fw-bold">Joined</p>
|
||||
<p>{{ $user->getJoinDate() }}</p>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<p class="fw-bold">Last Seen</p>
|
||||
<p>{{ $user->getLastSeen() }}</p>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<p class="fw-bold">Visits</p>
|
||||
<p>0</p>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="mt-1 mb-1" />
|
||||
@auth
|
||||
<a href="https://www.gtoria.local/todo123" class="ms-auto text-decoration-none link-danger">Report <i class="fa-solid fa-circle-exclamation"></i></a>
|
||||
@endauth
|
||||
</div>
|
||||
|
||||
<x-MiniCard class="mt-3 d-flex">
|
||||
<x-slot name="title">
|
||||
Official Badges
|
||||
</x-slot>
|
||||
<x-slot name="body">
|
||||
<p class="text-muted">todo</p>
|
||||
</x-slot>
|
||||
</x-MiniCard>
|
||||
|
||||
<x-MiniCard class="mt-3 d-flex">
|
||||
<x-slot name="title">
|
||||
Badges
|
||||
</x-slot>
|
||||
<x-slot name="body">
|
||||
<p class="text-muted">todo</p>
|
||||
</x-slot>
|
||||
</x-MiniCard>
|
||||
<div class="container-lg my-4 graphictoria-smaller-page">
|
||||
{{-- User pane --}}
|
||||
<div class="card p-2">
|
||||
<div class="d-flex">
|
||||
<div class="pe-3">
|
||||
<img class="img-fluid border graphictora-user-circle m-1" src="{{ asset('/images/testing/headshot.png') }}" alt="User avatar of {{ $user->username }}" width="120px" />
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<x-MiniCard class="mt-3 mt-md-0 d-flex">
|
||||
<x-slot name="title">
|
||||
Games
|
||||
</x-slot>
|
||||
<x-slot name="body">
|
||||
<p class="text-muted">todo</p>
|
||||
</x-slot>
|
||||
</x-MiniCard>
|
||||
|
||||
<x-MiniCard class="mt-3 d-flex">
|
||||
<x-slot name="title">
|
||||
Favorites
|
||||
</x-slot>
|
||||
<x-slot name="body">
|
||||
<p class="text-muted">todo</p>
|
||||
</x-slot>
|
||||
</x-MiniCard>
|
||||
|
||||
<x-MiniCard class="mt-3 d-flex">
|
||||
<x-slot name="title">
|
||||
Friends
|
||||
</x-slot>
|
||||
<x-slot name="body">
|
||||
<p class="text-muted">todo</p>
|
||||
</x-slot>
|
||||
</x-MiniCard>
|
||||
<div class="flex-fill d-flex flex-column p-2">
|
||||
{{-- TODO: XlXi: Advanced presence --}}
|
||||
<h4 class="mb-0">
|
||||
{{ $user->username }}
|
||||
<span @class([
|
||||
'text-muted' => !$user->isOnline(),
|
||||
'text-success' => $user->isOnline()
|
||||
])>({{ $user->isOnline() ? 'Online' : 'Offline' }})</span>
|
||||
</h4>
|
||||
<p>"This is my current status!"</p>
|
||||
<div class="d-md-flex mt-auto">
|
||||
<a href="#" class="btn btn-primary ms-auto">Send Message</a>
|
||||
<a href="#" class="btn btn-success ms-1">Add Friend</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- About pane --}}
|
||||
<h4 class="mt-2">About</h4>
|
||||
<div class="card p-2">
|
||||
@if($user->biography)
|
||||
<p>{{ $user->biography }}</p>
|
||||
@else
|
||||
<i class="text-muted">This user has no description.</i>
|
||||
@endif
|
||||
<hr class="my-2" />
|
||||
<div class="d-flex">
|
||||
{{-- TODO: XlXi: convert this to a route --}}
|
||||
<a href="https://www.gtoria.local/report/user/notfinishedtodo" target="_blank" class="text-decoration-none link-danger ms-auto">Report <i class="fa-solid fa-circle-exclamation"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Games pane --}}
|
||||
<h4 class="mt-2">Games</h4>
|
||||
<div class="card p-3">
|
||||
<div>
|
||||
{{-- XlXi: just reuse the shop cards for this lol --}}
|
||||
{{-- XlXi: https://cdn.discordapp.com/attachments/845538783592054795/1028135570335092826/unknown.png --}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
{{-- Badges pane --}}
|
||||
<h4 class="mt-2">Badges</h4>
|
||||
<div class="card p-2">
|
||||
{{-- TODO: XlXi: badges --}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
{{-- Friends pane --}}
|
||||
<h4 class="mt-2">Friends</h4>
|
||||
<div class="card p-2">
|
||||
{{-- TODO: XlXi: friends --}}
|
||||
{{-- TODO: XlXi: Sort friends by online --}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Groups pane --}}
|
||||
<h4 class="mt-2">Groups</h4>
|
||||
<div class="card p-2">
|
||||
|
||||
</div>
|
||||
|
||||
{{-- Statistics pane --}}
|
||||
<h4 class="mt-2">Statistics</h4>
|
||||
<div class="card p-3">
|
||||
<div class="row text-center">
|
||||
<div class="col">
|
||||
<p class="fw-bold">Joined</p>
|
||||
<p>{{ $user->getJoinDate() }}</p>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p class="fw-bold">Last Seen</p>
|
||||
<p>{{ $user->getLastSeen() }}</p>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p class="fw-bold">Visits</p>
|
||||
<p>todo</p>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p class="fw-bold">Forum Posts</p>
|
||||
<p>todo</p>
|
||||
</div>
|
||||
</div>
|
||||
<x-MiniCard class="mt-3 d-flex">
|
||||
<x-slot name="title">
|
||||
Groups
|
||||
</x-slot>
|
||||
<x-slot name="body">
|
||||
<p class="text-muted">todo</p>
|
||||
</x-slot>
|
||||
</x-MiniCard>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -8,6 +8,31 @@
|
|||
@section('content')
|
||||
<div id="gt-settings-main" class="container mx-auto my-2">
|
||||
<h4 class="my-auto">Settings</h4>
|
||||
<x-loader />
|
||||
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item">
|
||||
<button class="nav-link active">Account</button>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<button class="nav-link">Security</button>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<button class="nav-link">Privacy</button>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<button class="nav-link">Appearance</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="card p-2">
|
||||
<h5>Account Settings</h5>
|
||||
<div class="row">
|
||||
<div class="col-3 fw-bold">
|
||||
<p>Username</p>
|
||||
</div>
|
||||
<div class="col-9">
|
||||
<p>XlXi</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -11,6 +11,7 @@ mix.js('resources/js/app.js', 'public/js')
|
|||
.js('resources/js/pages/Maintenance.js', 'public/js')
|
||||
.js('resources/js/pages/Dashboard.js', 'public/js')
|
||||
.js('resources/js/pages/Shop.js', 'public/js')
|
||||
.js('resources/js/pages/Games.js', 'public/js')
|
||||
.js('resources/js/pages/Item.js', 'public/js')
|
||||
.js('resources/js/pages/SiteConfiguration.js', 'public/js/adm')
|
||||
.react()
|
||||
|
|
|
|||
Loading…
Reference in New Issue