feat: Nova homepage, profile redesign, and legacy view system overhaul
Homepage
- Add HomepageService with hero, trending (award-weighted), fresh uploads,
popular tags, creator spotlight (weekly uploads ranking), and news sections
- Add React components: HomePage, HomeHero, HomeTrending, HomeFresh,
HomeTags, HomeCreators, HomeNews (lazy-loaded below the fold)
- Wire home.blade.php with JSON props, SEO meta, JSON-LD, and hero preload
- Add HomePage.jsx to vite.config.js inputs
Profile page
- Hero banner with random user artwork as background + dark gradient overlay
- Favourites section uses real Artwork models + <x-artwork-card> for CDN URLs
- Newest artworks grid: gallery-grid → grid grid-cols-2 gap-4
Edit Profile page (user.blade.php)
- Add hero banner (featured wallpaper/photography via artwork_features,
content_type_id IN [2,3]) sourced in UserController
- Remove bg-deep from outer wrapper; card backgrounds: bg-panel → bg-nova-800
- Remove stray AI-generated tag fragment from template
Author profile links
- Fix all /@username routes in: HomepageService, MonthlyCommentatorsController,
LatestCommentsController, MyBuddiesController and corresponding blade views
Legacy view namespace
- Register View::addNamespace('legacy', resource_path('views/_legacy'))
in AppServiceProvider::boot()
- Convert all view('legacy.x') and @include('legacy.x') calls to legacy::x
- Migrate legacy views to resources/views/_legacy/ with namespace support
This commit is contained in:
2
resources/views/_legacy/_artwork_card.blade.php
Normal file
2
resources/views/_legacy/_artwork_card.blade.php
Normal file
@@ -0,0 +1,2 @@
|
||||
{{-- Shim for legacy artwork card includes. Points to new web partial. --}}
|
||||
@include('web.partials._artwork_card')
|
||||
180
resources/views/_legacy/_toolbar.blade.php
Normal file
180
resources/views/_legacy/_toolbar.blade.php
Normal file
@@ -0,0 +1,180 @@
|
||||
<nav class="navbar yamm navbar-skinbase navbar-fixed-top" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#mainToolbarNavCollapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a href="/" class="navbar-brand sb_toolbarLogo" title="SkinBase">SkinBase</a>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse" id="mainToolbarNavCollapse">
|
||||
<form class="hidden-xs navbar-form navbar-left" action="/search" method="get" id="search_box">
|
||||
<input type="text" name="q" value="{{ request('q') }}">
|
||||
<input type="hidden" name="group" value="all">
|
||||
<button type="submit"><i class="fa fa-search fa-fw"></i></button>
|
||||
</form>
|
||||
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="dropdown yamm-fw">
|
||||
<a href="#" class="dropdown-toggle c-white" data-toggle="dropdown" data-hover="dropdown" data-close-others="true">
|
||||
<i class="fa fa-cloud"></i> Browse <i class="fa fa-angle-down"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<div class="yamm-content">
|
||||
<div class="row">
|
||||
<div class="col-xs-6 col-sm-3 col-md-3 menu_box">
|
||||
<i class="fa fa-archive fa-fw"></i> Browse Artworks:<br>
|
||||
<div class="divider"></div>
|
||||
<ul class="submenu">
|
||||
<li><a href="/browse"><i class="fa fa-cloud fa-fw"></i> All Artworks</a></li>
|
||||
<li><a href="/photography"><i class="fa fa-photo fa-fw"></i> Photography</a></li>
|
||||
<li><a href="/wallpapers"><i class="fa fa-photo fa-fw"></i> Wallpapers</a></li>
|
||||
<li><a href="/skins"><i class="fa fa-photo fa-fw"></i> Skins</a></li>
|
||||
<li><a href="/other"><i class="fa fa-photo fa-fw"></i> Other</a></li>
|
||||
<li><a href="/featured-artworks"><i class="fa fa-trophy fa-fw"></i> Featured</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-6 col-sm-3 col-md-3">
|
||||
<i class="fa fa-eye fa-fw"></i> View:<br>
|
||||
<div class="divider"></div>
|
||||
<ul class="submenu">
|
||||
<li><a href="/forum"><i class="fa fa-comments fa-fw"></i> Forum</a></li>
|
||||
<li><a href="/chat"><i class="fa fa-comments fa-fw"></i> Chat</a></li>
|
||||
<li><a href="/browse-categories"><i class="fa fa-cloud fa-fw"></i> Categories</a></li>
|
||||
<li><a href="/latest-artworks"><i class="fa fa-trophy fa-fw"></i> Latest Uploads</a></li>
|
||||
<li><a href="/daily-uploads"><i class="fa fa-trophy fa-fw"></i> Recent Uploads</a></li>
|
||||
<li><a href="/today-in-history"><i class="fa fa-trophy fa-fw"></i> Today in History</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-6 col-sm-3 col-md-3">
|
||||
<i class="fa fa-users fa-fw"></i> Authors:<br>
|
||||
<div class="divider"></div>
|
||||
<ul class="submenu">
|
||||
<li><a href="/interviews"><i class="fa fa-users fa-fw"></i> Interviews</a></li>
|
||||
<li><a href="/Members/MembersPhotos/545"><i class="fa fa-users fa-fw"></i> Members Photos</a></li>
|
||||
<li><a href="/top-authors"><i class="fa fa-users fa-fw"></i> Top Authors</a></li>
|
||||
<li><a href="/latest-comments"><i class="fa fa-bar-chart fa-fw"></i> Latest Comments</a></li>
|
||||
<li><a href="/monthly-commentators"><i class="fa fa-bar-chart fa-fw"></i> Monthly Top Comments</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-6 col-sm-3 col-md-3">
|
||||
<i class="fa fa-bar-chart fa-fw"></i> Statistics:<br>
|
||||
<div class="divider"></div>
|
||||
<ul class="submenu">
|
||||
<li><a href="/today-downloads"><i class="fa fa-bar-chart fa-fw"></i> Today Downloads</a></li>
|
||||
<li><a href="/top-favourites"><i class="fa fa-bar-chart fa-fw"></i> Top Favourites</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle c-white" data-toggle="dropdown" data-hover="dropdown" data-close-others="true">
|
||||
<i class="fa fa-list-ul"></i> Categories <i class="fa fa-angle-down"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="/photography"><i class="fa fa-camera"></i> Photography</a></li>
|
||||
<li><a href="/wallpapers"><i class="fa fa-desktop"></i> Wallpapers</a></li>
|
||||
<li><a href="/skins"><i class="fa fa-eye"></i> Skins</a></li>
|
||||
<li><a href="/other"><i class="fa fa-file-o"></i> Others</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a href="/browse-categories" class="btn_category"><i class="fa fa-list"></i> Categories List</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
@auth
|
||||
@php
|
||||
$userId = auth()->id();
|
||||
try {
|
||||
$uploadCount = \Illuminate\Support\Facades\DB::table('artworks')->where('user_id', $userId)->count();
|
||||
} catch (\Throwable $e) {
|
||||
$uploadCount = 0;
|
||||
}
|
||||
try {
|
||||
$favCount = \Illuminate\Support\Facades\DB::table('favourites')->where('user_id', $userId)->count();
|
||||
} catch (\Throwable $e) {
|
||||
$favCount = 0;
|
||||
}
|
||||
try {
|
||||
$msgCount = \Illuminate\Support\Facades\DB::table('messages')->where('reciever_id', $userId)->whereNull('read_at')->count();
|
||||
} catch (\Throwable $e) {
|
||||
$msgCount = 0;
|
||||
}
|
||||
try {
|
||||
$noticeCount = \Illuminate\Support\Facades\DB::table('notification')->where('user_id', $userId)->where('new', 1)->count();
|
||||
} catch (\Throwable $e) {
|
||||
$noticeCount = 0;
|
||||
}
|
||||
try {
|
||||
$profile = \Illuminate\Support\Facades\DB::table('user_profiles')->where('user_id', $userId)->first();
|
||||
$avatarHash = $profile->avatar_hash ?? null;
|
||||
} catch (\Throwable $e) {
|
||||
$avatarHash = null;
|
||||
}
|
||||
$displayName = auth()->user()->name ?: (auth()->user()->username ?? '');
|
||||
@endphp
|
||||
|
||||
<li class="hidden-xs hidden-sm menu_notice">
|
||||
<a href="/upload" title="Upload new Artwork"><i class="fa fa-upload fa-fw"></i><br> {{ $uploadCount }}</a>
|
||||
</li>
|
||||
<li class="hidden-xs hidden-sm menu_notice">
|
||||
<a href="/favourites/{{ $userId }}/{{ auth()->user()->username ?? '' }}" title="Your Favourite Artworks"><i class="fa fa-heart fa-fw"></i><br> {{ $favCount }}</a>
|
||||
</li>
|
||||
<li class="hidden-xs hidden-sm menu_notice">
|
||||
<a href="/messages" title="Messages"><i class="fa fa-envelope fa-fw"></i><br> {{ $msgCount }}</a>
|
||||
</li>
|
||||
<li class="hidden-xs hidden-sm menu_notice">
|
||||
<a href="/notices" title="Notices"><i class="fa fa-bell"></i><br> {{ $noticeCount }}</a>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle c-white" data-toggle="dropdown" data-hover="dropdown" data-close-others="true">
|
||||
<img src="{{ \App\Support\AvatarUrl::forUser((int) $userId, $avatarHash ?? null, 32) }}" alt="{{ $displayName }}" width="18">
|
||||
<span class="username">{{ $displayName }}</span>
|
||||
<i class="fa fa-angle-down"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="/upload"><i class="fa fa-upload"></i> Upload</a></li>
|
||||
<li><a href="{{ route('dashboard.artworks.index') }}"><i class="fa fa-cloud"></i> Edit Artworks</a></li>
|
||||
<li role="presentation" class="divider"></li>
|
||||
<li><a href="/statistics"><i class="fa fa-cog"></i> Statistics</a></li>
|
||||
<li><a href="/mybuddies.php"><i class="fa fa-cog"></i> My Followes</a></li>
|
||||
<li><a href="/buddies.php"><i class="fa fa-cog"></i> Who follows me</a></li>
|
||||
<li role="presentation" class="divider"></li>
|
||||
<li><a href="/recieved-comments"><i class="fa fa-cog"></i> Received Comments</a></li>
|
||||
<li><a href="/favourites/{{ $userId }}/{{ auth()->user()->username ?? '' }}"><i class="fa fa-cog"></i> My Favourites</a></li>
|
||||
<li><a href="/gallery/{{ $userId }}/{{ auth()->user()->username ?? '' }}"><i class="fa fa-cog"></i> My Gallery</a></li>
|
||||
<li role="presentation" class="divider"></li>
|
||||
<li><a href="/user"><i class="fa fa-cog"></i> Edit Profile</a></li>
|
||||
<li><a href="/profile/{{ $userId }}/{{ auth()->user()->username ?? '' }}"><i class="fa fa-cog"></i> View My Profile</a></li>
|
||||
<li class="dropdown-footer clearfix">
|
||||
<form method="POST" action="/logout" style="margin:0;">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-link" style="padding: 3px 20px;"> <i class="fa fa-power-off"></i> Logout</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="hidden-xs hidden-sm menu_chat">
|
||||
<span class="toggle_menu" title="Chat"><i class="fa fa-weixin fa-lg fa-fw"></i></span>
|
||||
</li>
|
||||
@else
|
||||
<li class="dropdown"><a href="/signup" title="Signup for a new account" class="c-white"><i class="fa fa-unlock fa-fw"></i> Join</a></li>
|
||||
<li class="dropdown"><a href="/login" title="Login to Skinbase account" class="c-white"><i class="fa fa-sign-in fa-fw"></i> Sign in</a></li>
|
||||
@endauth
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
17
resources/views/_legacy/home.blade.php
Normal file
17
resources/views/_legacy/home.blade.php
Normal file
@@ -0,0 +1,17 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@php
|
||||
use Illuminate\Support\Str;
|
||||
use Carbon\Carbon;
|
||||
use App\Services\LegacyService;
|
||||
@endphp
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid legacy-page">
|
||||
@include('legacy::home.featured')
|
||||
|
||||
@include('legacy::home.uploads')
|
||||
|
||||
@include('legacy::home.news')
|
||||
</div>
|
||||
@endsection
|
||||
46
resources/views/_legacy/home/featured.blade.php
Normal file
46
resources/views/_legacy/home/featured.blade.php
Normal file
@@ -0,0 +1,46 @@
|
||||
{{-- Featured row --}}
|
||||
<div class="row featured-row">
|
||||
<div class="col-md-4 col-sm-12">
|
||||
<div class="featured-card effect2">
|
||||
<div class="card-header">Featured Artwork</div>
|
||||
<div class="card-body text-center">
|
||||
<a href="/art/{{ data_get($featured, 'id') }}/{{ Str::slug(data_get($featured, 'name') ?? 'artwork') }}" class="thumb-link">
|
||||
@php
|
||||
$fthumb = data_get($featured, 'thumb_url') ?? data_get($featured, 'thumb');
|
||||
@endphp
|
||||
<img src="{{ $fthumb }}" class="img-responsive featured-img" alt="{{ data_get($featured, 'name') }}">
|
||||
</a>
|
||||
<div class="featured-title">{{ data_get($featured, 'name') }}</div>
|
||||
<div class="featured-author">by {{ data_get($featured, 'uname') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 col-sm-12">
|
||||
<div class="featured-card effect2">
|
||||
<div class="card-header">Featured by Members Vote</div>
|
||||
<div class="card-body text-center">
|
||||
<a href="/art/{{ data_get($memberFeatured, 'id') }}/{{ Str::slug(data_get($memberFeatured, 'name') ?? 'artwork') }}" class="thumb-link">
|
||||
@php
|
||||
$mthumb = data_get($memberFeatured, 'thumb_url') ?? data_get($memberFeatured, 'thumb');
|
||||
@endphp
|
||||
<img src="{{ $mthumb }}" class="img-responsive featured-img" alt="{{ data_get($memberFeatured, 'name') }}">
|
||||
</a>
|
||||
<div class="featured-title">{{ data_get($memberFeatured, 'name') }}</div>
|
||||
<div class="featured-author">by {{ data_get($memberFeatured, 'uname') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 col-sm-12">
|
||||
<div class="featured-card join-card effect2">
|
||||
<div class="card-header">Join to Skinbase World</div>
|
||||
<div class="card-body text-center">
|
||||
<a href="{{ route('register') }}" title="Join Skinbase">
|
||||
<img src="/gfx/sb_join.jpg" alt="Join SkinBase Community" class="img-responsive join-img center-block">
|
||||
</a>
|
||||
<div class="join-text">Join to Skinbase and be part of our great community! We have big collection of high quality Photography, Wallpapers and Skins for popular applications.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
84
resources/views/_legacy/home/news.blade.php
Normal file
84
resources/views/_legacy/home/news.blade.php
Normal file
@@ -0,0 +1,84 @@
|
||||
{{-- News and forum columns --}}
|
||||
<div class="row news-row">
|
||||
<div class="col-sm-6">
|
||||
@php
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Str;
|
||||
@endphp
|
||||
@forelse ($forumNews as $item)
|
||||
<div class="panel panel-skinbase effect2">
|
||||
<div class="panel-heading"><h4 class="panel-title">{{ $item->topic }}</h4></div>
|
||||
<div class="panel-body">
|
||||
<div class="text-muted news-head">
|
||||
Written by {{ $item->uname }} on {{ Carbon::parse($item->post_date)->format('j F Y \@ H:i') }}
|
||||
</div>
|
||||
{!! Str::limit(strip_tags($item->preview ?? ''), 240, '...') !!}
|
||||
<br>
|
||||
<a class="clearfix btn btn-xs btn-info" href="{{ route('forum.thread.show', ['thread' => $item->topic_id, 'slug' => Str::slug($item->topic ?? '')]) }}" title="{{ strip_tags($item->topic) }}">More</a>
|
||||
</div>
|
||||
</div>
|
||||
@empty
|
||||
<p>No forum news available.</p>
|
||||
@endforelse
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
@forelse ($ourNews as $news)
|
||||
<div class="panel panel-skinbase effect2">
|
||||
<div class="panel-heading"><h3 class="panel-title">{{ $news->headline }}</h3></div>
|
||||
<div class="panel-body">
|
||||
<div class="text-muted news-head">
|
||||
<i class="fa fa-user"></i> {{ $news->uname }}
|
||||
<i class="fa fa-calendar"></i> {{ Carbon::parse($news->create_date)->format('j F Y \@ H:i') }}
|
||||
<i class="fa fa-info"></i> {{ $news->category_name }}
|
||||
<i class="fa fa-info"></i> {{ $news->views }} reads
|
||||
<i class="fa fa-comment"></i> {{ $news->num_comments }} comments
|
||||
</div>
|
||||
|
||||
@if (!empty($news->picture))
|
||||
@php $nid = floor($news->news_id / 100); @endphp
|
||||
<div class="col-md-4">
|
||||
<img src="/archive/news/{{ $nid }}/{{ $news->picture }}" class="img-responsive" alt="{{ $news->headline }}">
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
{!! $news->preview !!}
|
||||
</div>
|
||||
@else
|
||||
{!! $news->preview !!}
|
||||
@endif
|
||||
|
||||
<a class="clearfix btn btn-xs btn-info text-white" href="/news/{{ $news->news_id }}/{{ Str::slug($news->headline ?? '') }}">More</a>
|
||||
</div>
|
||||
</div>
|
||||
@empty
|
||||
<p>No news available.</p>
|
||||
@endforelse
|
||||
|
||||
{{-- Site info --}}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>Info</strong></div>
|
||||
<div class="panel-body">
|
||||
<h4>Photography, Wallpapers and Skins... Thats Skinbase</h4>
|
||||
<p>Skinbase is the site dedicated to <strong>Photography</strong>, <strong>Wallpapers</strong> and <strong>Skins</strong> for <u>popular applications</u> for every major operating system like Windows, Mac OS X, Linux, iOS and Android</p>
|
||||
<em>Our members every day uploads new artworks to our site, so don't hesitate and check Skinbase frequently for updates. We also have forum where you can discuss with other members with anything.</em>
|
||||
<p>On the site toolbar you can click on Categories and start browsing our atwork (<i>photo</i>, <i>desktop themes</i>, <i>pictures</i>) and of course you can <u>download</u> them for free!</p>
|
||||
<p>We are also active on all major <b>social</b> sites, find us there too</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Latest forum activity --}}
|
||||
<div class="panel panel-default activity-panel">
|
||||
<div class="panel-heading"><strong>Latest Forum Activity</strong></div>
|
||||
<div class="panel-body">
|
||||
<div class="list-group effect2">
|
||||
@forelse ($latestForumActivity as $topic)
|
||||
<a class="list-group-item" href="{{ route('forum.thread.show', ['thread' => $topic->topic_id, 'slug' => Str::slug($topic->topic ?? '')]) }}">
|
||||
{{ $topic->topic }} <span class="badge badge-info">{{ $topic->numPosts }}</span>
|
||||
</a>
|
||||
@empty
|
||||
<p>No recent forum activity.</p>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
12
resources/views/_legacy/home/uploads.blade.php
Normal file
12
resources/views/_legacy/home/uploads.blade.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<div class="gallery-grid">
|
||||
@foreach ($latestUploads as $upload)
|
||||
<div class="thumb-card effect2">
|
||||
@php
|
||||
$t = \App\Services\ThumbnailPresenter::present($upload, 'md');
|
||||
@endphp
|
||||
<a href="/art/{{ $t['id'] }}/{{ Str::slug($t['title'] ?: 'artwork') }}" title="{{ $t['title'] }}" class="thumb-link">
|
||||
<img src="{{ $t['url'] }}" @if(!empty($t['srcset'])) srcset="{{ $t['srcset'] }}" @endif alt="{{ $t['title'] }}" class="img-responsive">
|
||||
</a>
|
||||
</div>
|
||||
@endforeach
|
||||
</div> <!-- end .gallery-grid -->
|
||||
97
resources/views/_legacy/interview.blade.php
Normal file
97
resources/views/_legacy/interview.blade.php
Normal file
@@ -0,0 +1,97 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid legacy-page">
|
||||
<div class="effect2 page-header-wrap">
|
||||
<header class="page-heading">
|
||||
<h1 class="page-header">Interview</h1>
|
||||
<p>{{ $ar->headline ?? '' }}</p>
|
||||
<div style="location_bar">
|
||||
<a href="/interviews" class="btn btn-xs btn-default" title="List of all Interviews"><i class="fa fa-list fa-fw"></i> Interviews List</a>
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-9">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<h1 class="skinTitle">{{ $ar->headline }}</h1>
|
||||
<div>{!! $ar->tekst !!}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="skinTitle">User Comments</h2>
|
||||
|
||||
@foreach($comments as $comment)
|
||||
@php
|
||||
$local_date = date('j.F.y @ H:i:s', strtotime($comment->datum));
|
||||
$user_id = $comment->user_id ?? null;
|
||||
@endphp
|
||||
<table width="100%" cellspacing="1" cellpadding="1" class="MojText" border="0" style="background:#eee;">
|
||||
<tr>
|
||||
<td rowspan="3" valign="top" width="100" style="background:#fff">
|
||||
@if(!empty($comment->user_id) && !empty($comment->icon))
|
||||
<div align="center"><a href="/profile/{{ $comment->user_id }}"><img src="{{ \App\Support\AvatarUrl::forUser((int) $comment->user_id, null, 50) }}" width="50" height="50" border="0" alt="" /></a></div>
|
||||
@endif
|
||||
<br/>Posted by: <b><a href="/profile/{{ $comment->user_id ?? '' }}">{{ $comment->author }}</a></b><br/>
|
||||
Posts: {{ $postCounts[$comment->author] ?? 0 }}
|
||||
<div align="center"><img src="/gfx/member_stars/{{ $comment->user_type ?? 0 }}.jpg" title="" /></div>
|
||||
</td>
|
||||
<td valign="top" height="10" style="background:#eee"> {{ $local_date }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td height="50" style="background:#fff;padding-left:13px; padding-right:3px;">{!! $comment->tekst !!}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="bottom" align="center" height="10" style="background:#fff;">
|
||||
@if(!empty($comment->signature))
|
||||
{!! nl2br(e($comment->signature)) !!}
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br />
|
||||
@endforeach
|
||||
|
||||
@php
|
||||
$status = $_SESSION['web_login']['status'] ?? false;
|
||||
$user_type = $_SESSION['web_login']['user_type'] ?? 0;
|
||||
@endphp
|
||||
|
||||
@if(!$status || $user_type < 2)
|
||||
<h1>Please login first</h1>
|
||||
@else
|
||||
<h2 class="skinTitle">Write comment</h2>
|
||||
<form action="{{ url()->current() }}" method="post">
|
||||
@csrf
|
||||
<textarea name="comment" style="width:98%; height:215px;" class="textarea"></textarea><br />
|
||||
<input type="hidden" name="interview_id" value="{{ $ar->id }}">
|
||||
<input type="hidden" name="action" value="store">
|
||||
<button type="submit" class="btn btn-success">Submit</button>
|
||||
</form>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<div style="margin-left:4px; float:right;width:300px;border-left :dotted 1px #eee; padding-left:10px;">
|
||||
<br/><br/>
|
||||
@php \App\Banner::ShowBanner300x250(); @endphp
|
||||
<br/><br/>
|
||||
|
||||
@if(!empty($ar->username))
|
||||
@php $username = DB::table('users')->where('uname', $ar->username)->value('uname'); @endphp
|
||||
<div class="interviewGuy">{{ $username }} Gallery (random order):</div><br/>
|
||||
@foreach($artworks as $artwork)
|
||||
@php $nid = (int)($artwork->id / 100); @endphp
|
||||
<a href="/art/{{ $artwork->id }}/{{ \Illuminate\Support\Str::slug($artwork->name ?? '') }}">
|
||||
<img src="/files/archive/shots/{{ $nid }}/{{ $artwork->picture }}" alt="" style="max-width:100%;" />
|
||||
</a>
|
||||
<br/><br/>
|
||||
@endforeach
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
41
resources/views/_legacy/interviews.blade.php
Normal file
41
resources/views/_legacy/interviews.blade.php
Normal file
@@ -0,0 +1,41 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid legacy-page">
|
||||
<div class="effect2 page-header-wrap">
|
||||
<header class="page-heading">
|
||||
<h1 class="page-header">{{ $page_title ?? 'Interviews' }}</h1>
|
||||
<p>List of interviews and their authors.</p>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
@php \App\Banner::ShowResponsiveAd(); @endphp
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<table class="table table-bordered table-striped">
|
||||
<tbody>
|
||||
@foreach($interviews as $interview)
|
||||
<tr>
|
||||
<td style="width:60px;">
|
||||
@if(!empty($interview->icon))
|
||||
<a href="/profile/{{ $interview->user_id }}/{{ \Illuminate\Support\Str::slug($interview->uname ?? '') }}">
|
||||
<img src="{{ \App\Support\AvatarUrl::forUser((int) $interview->user_id, null, 50) }}" width="50" height="50" alt="">
|
||||
</a>
|
||||
@else
|
||||
<img src="/gfx/avatar.jpg" alt="">
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<a href="/interview/{{ $interview->id }}/{{ \Illuminate\Support\Str::slug($interview->headline ?? '') }}">{{ $interview->headline }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
41
resources/views/_legacy/latest-artworks.blade.php
Normal file
41
resources/views/_legacy/latest-artworks.blade.php
Normal file
@@ -0,0 +1,41 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid legacy-page">
|
||||
<div class="effect2 page-header-wrap">
|
||||
<header class="page-heading">
|
||||
<h1 class="page-header">Latest Artworks</h1>
|
||||
<p>List of recently uploaded Artworks - <strong>Skins</strong>, <strong>Photography</strong> and <strong>Wallpapers</strong>.</p>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default uploads-panel effect2">
|
||||
<div class="panel-body">
|
||||
<div class="gallery-grid">
|
||||
@if($artworks)
|
||||
@foreach($artworks as $art)
|
||||
<div class="thumb-card effect2">
|
||||
@if (!empty($art->category_name))
|
||||
<div class="ribbon gid_{{ $art->gid_num ?? 0 }}" title="{{ $art->category_name }}"><span>{{ $art->category_name }}</span></div>
|
||||
@endif
|
||||
<a href="/art/{{ $art->id }}/{{ Str::slug($art->name ?? '') }}" class="thumb-link" title="{{ $art->name }}">
|
||||
<img src="{{ $art->thumb_url ?? '/gfx/sb_join.jpg' }}" @if(!empty($art->thumb_srcset)) srcset="{{ $art->thumb_srcset }}" @endif alt="{{ $art->name }}" class="img-responsive" loading="lazy" decoding="async">
|
||||
</a>
|
||||
<div class="thumb-meta">
|
||||
<div class="thumb-title">{{ $art->name }}</div>
|
||||
<div class="thumb-author text-muted">by {{ $art->uname ?? 'Unknown' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
@else
|
||||
<p class="text-muted">No artworks found.</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="paginationMenu text-center">
|
||||
@if($artworks){{ $artworks->withQueryString()->links('pagination::bootstrap-4') }}@endif
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
55
resources/views/_legacy/latest-comments.blade.php
Normal file
55
resources/views/_legacy/latest-comments.blade.php
Normal file
@@ -0,0 +1,55 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid legacy-page">
|
||||
<div class="effect2 page-header-wrap">
|
||||
<header class="page-heading">
|
||||
<h1 class="page-header">{{ $page_title }}</h1>
|
||||
<p>List of artwork with latest comments received.</p>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<div class="masonry">
|
||||
@foreach ($comments as $comment)
|
||||
<div class="masonry_item col-sm-6 col-md-4">
|
||||
<div class="comment_box effect3">
|
||||
<div class="cb_image">
|
||||
<a href="/profile/{{ $comment->commenter_id }}/{{ rawurlencode($comment->uname) }}">
|
||||
<img src="{{ \App\Support\AvatarUrl::forUser((int) $comment->commenter_id, null, 50) }}" width="50" height="50" class="comment_avatar" alt="{{ $comment->uname }}">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="bubble_comment panel panel-skinbase">
|
||||
<div class="panel-heading">
|
||||
<div class="pull-right">{{
|
||||
\Carbon\Carbon::parse($comment->datetime)->diffForHumans() }}
|
||||
</div>
|
||||
<h5 class="panel-title">Comment by: <a href="/profile/{{ $comment->commenter_id }}/{{ rawurlencode($comment->uname) }}">{{ $comment->uname }}</a></h5>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="comment_box_image">
|
||||
<a href="/art/{{ $comment->id }}/{{ $comment->artwork_slug }}">
|
||||
<img src="{{ $comment->thumb }}" alt="{{ $comment->name }}" class="img-thumbnail img-responsive">
|
||||
</a>
|
||||
</div>
|
||||
<div class="comment_text mt-2">
|
||||
{!! nl2br(e($comment->comment_description)) !!}
|
||||
</div>
|
||||
|
||||
@if (!empty($comment->signature))
|
||||
<div class="panel-footer comment-footer mt-2">
|
||||
{!! nl2br(e($comment->signature)) !!}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="paginationMenu text-center">
|
||||
{{ $comments->links('pagination::bootstrap-4') }}
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
57
resources/views/_legacy/monthly-commentators.blade.php
Normal file
57
resources/views/_legacy/monthly-commentators.blade.php
Normal file
@@ -0,0 +1,57 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid legacy-page">
|
||||
<div class="effect2 page-header-wrap">
|
||||
<header class="page-heading">
|
||||
<h1 class="page-header">{{ $page_title }}</h1>
|
||||
<p>List of users who post the most comments in the current month.</p>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<div class="container-main">
|
||||
<div class="panel panel-default effect2">
|
||||
<div class="panel-body">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Thumb</th>
|
||||
<th>Name</th>
|
||||
<th>Level</th>
|
||||
<th>Country</th>
|
||||
<th>Comments</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($rows as $row)
|
||||
<tr>
|
||||
<td width="50" class="text-center">
|
||||
<a href="/profile/{{ (int)$row->user_id }}/{{ rawurlencode($row->uname) }}">
|
||||
<img src="{{ \App\Support\AvatarUrl::forUser((int) $row->user_id, null, 32) }}" width="30" alt="{{ $row->uname }}">
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="/profile/{{ (int)$row->user_id }}/{{ rawurlencode($row->uname) }}">{{ $row->uname }}</a>
|
||||
</td>
|
||||
<td width="100" class="text-center">
|
||||
<img src="/gfx/member_stars/{{ (int)$row->user_type }}.gif" alt="level">
|
||||
</td>
|
||||
<td width="100" class="text-center">
|
||||
@if (!empty($row->country_flag))
|
||||
<img width="20" title="{{ $row->country_name }}" src="/gfx/flags/{{ rawurlencode($row->country_flag) }}" alt="{{ $row->country_name }}">
|
||||
@endif
|
||||
</td>
|
||||
<td width="100" class="text-center">{{ (int)$row->num_comments }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="paginationMenu text-center">
|
||||
{{ $rows->withQueryString()->links('pagination::bootstrap-4') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
57
resources/views/_legacy/mybuddies.blade.php
Normal file
57
resources/views/_legacy/mybuddies.blade.php
Normal file
@@ -0,0 +1,57 @@
|
||||
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid legacy-page">
|
||||
<div class="effect2 page-header-wrap">
|
||||
<header class="page-heading">
|
||||
<h1 class="page-header">{{ $page_title ?? 'My Buddies' }}</h1>
|
||||
<p>List of members you are following</p>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="icon-grid">
|
||||
@forelse($buddies as $b)
|
||||
@php
|
||||
$icon = $b->icon ?? 'default.jpg';
|
||||
$uname = $b->uname ?? 'Unknown';
|
||||
$friendId = $b->friend_id ?? $b->friendId ?? null;
|
||||
@endphp
|
||||
|
||||
@php $buddyUrl = ($b->user_username ?? null) ? '/@' . $b->user_username : '/profile/' . $friendId; @endphp
|
||||
<div class="icon-flex">
|
||||
<div>
|
||||
<a href="{{ $buddyUrl }}">
|
||||
<h4>{{ $uname }}</h4>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a href="{{ $buddyUrl }}">
|
||||
<img src="{{ \App\Support\AvatarUrl::forUser((int) $friendId, null, 50) }}" alt="{{ $uname }}">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@if(auth()->check() && auth()->id() == ($b->user_id ?? null))
|
||||
<div>
|
||||
<form method="POST" action="{{ route('legacy.mybuddies.delete', ['id' => $b->id]) }}" onsubmit="return confirm('Really Remove From Friends List: {{ addslashes($uname) }}?');">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button class="btn btn-link" type="submit"><img src="/gfx/icon_delete.gif" alt="remove"></button>
|
||||
</form>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
@empty
|
||||
<p>No buddies yet.</p>
|
||||
@endforelse
|
||||
</div>
|
||||
|
||||
@if(method_exists($buddies, 'links'))
|
||||
<div class="mt-3">{{ $buddies->links() }}</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
77
resources/views/_legacy/news.blade.php
Normal file
77
resources/views/_legacy/news.blade.php
Normal file
@@ -0,0 +1,77 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid legacy-page">
|
||||
<div class="page-heading">
|
||||
<h1 class="page-header">{{ $news->headline ?? 'News' }}</h1>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading">
|
||||
<i class="fa fa-user"></i>
|
||||
<a href="/profile/{{ $news->user_id ?? '' }}/{{ Str::slug($news->uname ?? '') }}">{{ $news->uname ?? 'Unknown' }}</a>
|
||||
<i class="fa fa-calendar"></i>
|
||||
{{ date('j.F.y @ H:i:s', strtotime($news->create_date ?? now())) }}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<h1 class="panel-title" style="font-size:26px;color:#000;">{!! nl2br(e($news->headline ?? '')) !!}</h1>
|
||||
<br>
|
||||
<p>{!! html_entity_decode(stripslashes($news->content ?? '')) !!}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="lead">User Comments:</h3>
|
||||
|
||||
@foreach($comments as $ar)
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<i class="fa fa-user"></i>
|
||||
<a href="/profile/{{ $ar->user_id ?? '' }}/{{ Str::slug($ar->uname ?? '') }}">{{ $ar->uname ?? 'Unknown' }}</a>
|
||||
<i class="fa fa-calendar"></i>
|
||||
{{ date('j.F.y @ H:i:s', strtotime($ar->posted ?? now())) }}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
@if(!empty($ar->icon))
|
||||
<div style="float:right;padding-left:20px;">
|
||||
<a href="/profile/{{ $ar->user_id ?? '' }}/{{ Str::slug($ar->uname ?? '') }}">
|
||||
<img src="{{ \App\Support\AvatarUrl::forUser((int) ($ar->user_id ?? 0), null, 50) }}" width="50" height="50" alt="">
|
||||
</a>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div>{!! nl2br(e($ar->message ?? '')) !!}</div>
|
||||
|
||||
@if(!empty($ar->signature))
|
||||
<div class="label label-info">{!! nl2br(e($ar->signature)) !!}</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
{{-- Comment form (legacy) --}}
|
||||
@php
|
||||
$status = $_SESSION['web_login']['status'] ?? false;
|
||||
$user_type = $_SESSION['web_login']['user_type'] ?? 0;
|
||||
@endphp
|
||||
|
||||
@if(!$status && $user_type < 2)
|
||||
<div class="alert alert-warning"><i class="fa fa-warning"></i> You have to login to write comment</div>
|
||||
@else
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><i class="fa fa-comment"></i> Write comment</div>
|
||||
<div class="panel-body">
|
||||
<form action="/news/{{ $news->news_id ?? '' }}/{{ Str::slug($news->headline ?? '') }}" method="post" class="form">
|
||||
@csrf
|
||||
<textarea name="comment" style="width:100%; height:215px;" class="tinymce"></textarea><br>
|
||||
<input type="hidden" name="news_id" value="{{ $news->news_id ?? '' }}">
|
||||
<input type="hidden" name="confirm" value="true">
|
||||
<button type="submit" class="btn btn-success">Post Comment</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
@endsection
|
||||
692
resources/views/_legacy/profile.blade.php
Normal file
692
resources/views/_legacy/profile.blade.php
Normal file
@@ -0,0 +1,692 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@php
|
||||
$uname = $user->username ?? $user->name ?? 'Unknown';
|
||||
$displayName = $user->name ?? $uname;
|
||||
$avatarUrl = \App\Support\AvatarUrl::forUser((int) $user->id, $user->profile?->avatar_hash, 128);
|
||||
|
||||
$genderMap = [
|
||||
'M' => ['label' => 'Male', 'icon' => 'fa-mars', 'color' => 'text-blue-400'],
|
||||
'F' => ['label' => 'Female', 'icon' => 'fa-venus', 'color' => 'text-pink-400'],
|
||||
'X' => ['label' => 'N/A', 'icon' => 'fa-question', 'color' => 'text-gray-400'],
|
||||
];
|
||||
$genderCode = strtoupper((string) ($profile?->gender ?? 'X'));
|
||||
$gender = $genderMap[$genderCode] ?? $genderMap['X'];
|
||||
|
||||
$birthdate = null;
|
||||
if ($profile?->birthdate) {
|
||||
try {
|
||||
$bd = \Carbon\Carbon::parse($profile->birthdate);
|
||||
if ($bd->year > 1900) {
|
||||
$birthdate = $bd->format('F d, Y');
|
||||
}
|
||||
} catch (\Throwable) {}
|
||||
}
|
||||
|
||||
$website = $profile?->website ?? null;
|
||||
if ($website && !preg_match('#^https?://#i', $website)) {
|
||||
$website = 'https://' . $website;
|
||||
}
|
||||
|
||||
$about = $profile?->about ?? null;
|
||||
|
||||
$lastVisit = null;
|
||||
if ($user->last_visit_at) {
|
||||
try { $lastVisit = \Carbon\Carbon::parse($user->last_visit_at); } catch (\Throwable) {}
|
||||
}
|
||||
|
||||
$socialIcons = [
|
||||
'twitter' => ['icon' => 'fa-brands fa-x-twitter', 'label' => 'X / Twitter'],
|
||||
'deviantart' => ['icon' => 'fa-brands fa-deviantart', 'label' => 'DeviantArt'],
|
||||
'instagram' => ['icon' => 'fa-brands fa-instagram', 'label' => 'Instagram'],
|
||||
'behance' => ['icon' => 'fa-brands fa-behance', 'label' => 'Behance'],
|
||||
'artstation' => ['icon' => 'fa-solid fa-palette', 'label' => 'ArtStation'],
|
||||
'youtube' => ['icon' => 'fa-brands fa-youtube', 'label' => 'YouTube'],
|
||||
'website' => ['icon' => 'fa-solid fa-link', 'label' => 'Website'],
|
||||
];
|
||||
|
||||
$seoPage = max(1, (int) request()->query('page', 1));
|
||||
$seoBase = url()->current();
|
||||
$seoQ = request()->query(); unset($seoQ['page']);
|
||||
$seoUrl = fn(int $p) => $seoBase . ($p > 1
|
||||
? '?' . http_build_query(array_merge($seoQ, ['page' => $p]))
|
||||
: (count($seoQ) ? '?' . http_build_query($seoQ) : ''));
|
||||
$seoPrev = $seoPage > 1 ? $seoUrl($seoPage - 1) : null;
|
||||
$seoNext = (isset($artworks) && method_exists($artworks, 'nextPageUrl')) ? $artworks->nextPageUrl() : null;
|
||||
@endphp
|
||||
|
||||
@push('head')
|
||||
<link rel="canonical" href="{{ $seoUrl($seoPage) }}">
|
||||
@if($seoPrev)<link rel="prev" href="{{ $seoPrev }}">@endif
|
||||
@if($seoNext)<link rel="next" href="{{ $seoNext }}">@endif
|
||||
<meta name="robots" content="index,follow">
|
||||
<meta property="og:title" content="Profile: {{ e($uname) }} – Skinbase.org">
|
||||
<meta property="og:image" content="{{ $avatarUrl }}">
|
||||
<meta property="og:url" content="{{ $page_canonical ?? url()->current() }}">
|
||||
<style>
|
||||
.profile-hero-bg {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.profile-hero-bg::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background:
|
||||
radial-gradient(ellipse at 20% 50%, rgba(77,163,255,.12), transparent 60%),
|
||||
radial-gradient(ellipse at 80% 20%, rgba(224,122,33,.08), transparent 50%);
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
}
|
||||
.nova-panel {
|
||||
background: var(--panel-dark);
|
||||
border: 1px solid var(--sb-line);
|
||||
border-radius: 0.75rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
.nova-panel-header {
|
||||
padding: 0.65rem 1rem;
|
||||
border-bottom: 1px solid var(--sb-line);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
font-weight: 600;
|
||||
font-size: 0.82rem;
|
||||
color: var(--sb-text);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
.nova-panel-body { padding: 1rem; }
|
||||
.stat-item { text-align: center; padding: 0.5rem 0.75rem; }
|
||||
.stat-item .stat-value {
|
||||
font-size: 1.15rem;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
line-height: 1.2;
|
||||
}
|
||||
.stat-item .stat-label {
|
||||
font-size: 0.65rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
color: var(--sb-muted);
|
||||
margin-top: 1px;
|
||||
}
|
||||
.profile-table td:first-child {
|
||||
color: var(--sb-muted);
|
||||
font-size: 0.75rem;
|
||||
white-space: nowrap;
|
||||
padding-right: 0.75rem;
|
||||
padding-top: 0.45rem;
|
||||
padding-bottom: 0.45rem;
|
||||
}
|
||||
.profile-table td:last-child {
|
||||
color: var(--sb-text);
|
||||
font-size: 0.82rem;
|
||||
text-align: right;
|
||||
}
|
||||
.profile-table tr {
|
||||
border-bottom: 1px solid rgba(42,42,51,0.5);
|
||||
}
|
||||
.profile-table tr:last-child { border-bottom: none; }
|
||||
.profile-table td { vertical-align: middle; }
|
||||
.comment-avatar {
|
||||
width: 38px; height: 38px;
|
||||
border-radius: 50%; object-fit: cover; flex-shrink: 0;
|
||||
}
|
||||
.follower-avatar {
|
||||
width: 34px; height: 34px;
|
||||
border-radius: 50%; object-fit: cover;
|
||||
border: 1px solid var(--sb-line);
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
.follower-avatar:hover { opacity: 0.85; }
|
||||
.fav-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(88px, 1fr));
|
||||
gap: 4px;
|
||||
}
|
||||
.fav-grid a img {
|
||||
width: 100%; aspect-ratio: 1; object-fit: cover;
|
||||
border-radius: 4px; transition: opacity 0.2s;
|
||||
display: block;
|
||||
}
|
||||
.fav-grid a:hover img { opacity: 0.82; }
|
||||
.follow-btn { transition: all 0.2s ease; }
|
||||
</style>
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
|
||||
{{-- ═══════════════════════════════════════════════════════════
|
||||
PROFILE HERO
|
||||
═══════════════════════════════════════════════════════════ --}}
|
||||
<div class="profile-hero-bg border-b border-[--sb-line]"
|
||||
@if(!empty($heroBgUrl))
|
||||
style="background: url('{{ $heroBgUrl }}') center/cover no-repeat;"
|
||||
@else
|
||||
style="background: linear-gradient(135deg, rgba(15,23,36,1) 0%, rgba(21,30,46,1) 50%, rgba(9,16,26,1) 100%);"
|
||||
@endif
|
||||
>
|
||||
{{-- Dark overlay so the content stays readable --}}
|
||||
@if(!empty($heroBgUrl))
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-[#0f1724]/95 via-[#0f1724]/80 to-[#0f1724]/60"></div>
|
||||
@endif
|
||||
<div class="relative z-10 max-w-screen-xl mx-auto px-4 py-8">
|
||||
<div class="flex flex-col sm:flex-row items-center sm:items-end gap-5">
|
||||
|
||||
{{-- Avatar --}}
|
||||
<div class="shrink-0">
|
||||
<img src="{{ $avatarUrl }}"
|
||||
alt="{{ e($uname) }}"
|
||||
class="w-24 h-24 sm:w-32 sm:h-32 rounded-full object-cover border-4 border-[--sb-line] shadow-lg">
|
||||
</div>
|
||||
|
||||
{{-- Name + meta --}}
|
||||
<div class="flex-1 text-center sm:text-left min-w-0">
|
||||
<h1 class="text-2xl sm:text-3xl font-bold text-white leading-tight truncate">
|
||||
{{ e($uname) }}
|
||||
</h1>
|
||||
@if($displayName && $displayName !== $uname)
|
||||
<p class="text-[--sb-muted] text-sm mt-0.5">{{ e($displayName) }}</p>
|
||||
@endif
|
||||
@if($countryName)
|
||||
<p class="text-[--sb-muted] text-sm mt-1 flex items-center justify-center sm:justify-start gap-1.5">
|
||||
@if($profile?->country_code)
|
||||
<img src="/gfx/flags/shiny/24/{{ rawurlencode($profile->country_code) }}.png"
|
||||
alt="{{ e($countryName) }}"
|
||||
class="w-5 h-auto rounded-sm inline-block"
|
||||
onerror="this.style.display='none'">
|
||||
@endif
|
||||
{{ e($countryName) }}
|
||||
</p>
|
||||
@endif
|
||||
@if($lastVisit)
|
||||
<p class="text-[--sb-muted] text-xs mt-1">
|
||||
<i class="fa-solid fa-clock fa-fw mr-1"></i>
|
||||
Last seen {{ $lastVisit->diffForHumans() }}
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{-- Action buttons --}}
|
||||
<div class="shrink-0 flex flex-col gap-2 items-center sm:items-end">
|
||||
@if(!$isOwner)
|
||||
@auth
|
||||
<div x-data="{
|
||||
following: {{ $viewerIsFollowing ? 'true' : 'false' }},
|
||||
count: {{ (int) $followerCount }},
|
||||
loading: false,
|
||||
async toggle() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const r = await fetch('{{ route('profile.follow', ['username' => strtolower((string)$uname)]) }}', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name=csrf-token]').content,
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
const d = await r.json();
|
||||
if (r.ok) { this.following = d.following; this.count = d.follower_count; }
|
||||
} catch(e) {}
|
||||
this.loading = false;
|
||||
}
|
||||
}">
|
||||
<button @click="toggle" :disabled="loading" class="follow-btn inline-flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium border transition-all"
|
||||
:class="following
|
||||
? 'bg-green-500/10 border-green-500/40 text-green-400 hover:bg-red-500/10 hover:border-red-500/40 hover:text-red-400'
|
||||
: 'bg-[--sb-blue]/10 border-[--sb-blue]/40 text-[--sb-blue] hover:bg-[--sb-blue]/20'">
|
||||
<i class="fa-solid fa-fw"
|
||||
:class="loading ? 'fa-circle-notch fa-spin' : (following ? 'fa-user-check' : 'fa-user-plus')"></i>
|
||||
<span x-text="following ? 'Following' : 'Follow'"></span>
|
||||
<span class="text-xs opacity-60" x-text="'(' + count + ')'"></span>
|
||||
</button>
|
||||
</div>
|
||||
@else
|
||||
<a href="{{ route('login') }}"
|
||||
class="inline-flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium border border-[--sb-blue]/40 text-[--sb-blue] hover:bg-[--sb-blue]/10 transition-all">
|
||||
<i class="fa-solid fa-user-plus fa-fw"></i> Follow
|
||||
<span class="text-xs opacity-60">({{ $followerCount }})</span>
|
||||
</a>
|
||||
@endauth
|
||||
@else
|
||||
<a href="{{ route('dashboard.profile') }}"
|
||||
class="inline-flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium border border-[--sb-line] text-[--sb-text] hover:bg-white/5 transition-all">
|
||||
<i class="fa-solid fa-pen fa-fw"></i> Edit Profile
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- ═══════════════════════════════════════════════════════════
|
||||
STATS STRIP
|
||||
═══════════════════════════════════════════════════════════ --}}
|
||||
<div class="bg-[--sb-panel2] border-b border-[--sb-line]">
|
||||
<div class="max-w-screen-xl mx-auto px-4">
|
||||
<div class="flex divide-x divide-[--sb-line] overflow-x-auto">
|
||||
@foreach([
|
||||
['value' => number_format($stats->uploads ?? 0), 'label' => 'Uploads', 'icon' => 'fa-cloud-arrow-up'],
|
||||
['value' => number_format($stats->downloads ?? 0), 'label' => 'Downloads', 'icon' => 'fa-download'],
|
||||
['value' => number_format($stats->profile_views ?? 0), 'label' => 'Profile Views', 'icon' => 'fa-eye'],
|
||||
['value' => number_format($followerCount), 'label' => 'Followers', 'icon' => 'fa-users'],
|
||||
['value' => number_format($stats->awards ?? 0), 'label' => 'Awards', 'icon' => 'fa-trophy'],
|
||||
] as $si)
|
||||
<div class="stat-item flex-1 py-3">
|
||||
<div class="stat-value">{{ $si['value'] }}</div>
|
||||
<div class="stat-label">
|
||||
<i class="fa-solid {{ $si['icon'] }} fa-fw mr-0.5"></i>{{ $si['label'] }}
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- ═══════════════════════════════════════════════════════════
|
||||
MAIN CONTENT
|
||||
═══════════════════════════════════════════════════════════ --}}
|
||||
<div class="max-w-screen-xl mx-auto px-4 py-6">
|
||||
<div class="flex flex-col lg:flex-row gap-5">
|
||||
|
||||
{{-- ─── LEFT COLUMN (artworks) ─── --}}
|
||||
<div class="flex-1 min-w-0 space-y-5">
|
||||
|
||||
{{-- Featured Artworks --}}
|
||||
@if(isset($featuredArtworks) && $featuredArtworks->isNotEmpty())
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-star text-yellow-400 fa-fw"></i>
|
||||
Featured Artworks
|
||||
</div>
|
||||
<div class="nova-panel-body">
|
||||
<div class="flex flex-col md:flex-row gap-4">
|
||||
@php $feat = $featuredArtworks->first() @endphp
|
||||
{{-- Main featured --}}
|
||||
<a href="/art/{{ $feat->id }}/{{ \Illuminate\Support\Str::slug($feat->name) }}"
|
||||
class="flex-1 group block min-w-0">
|
||||
<div class="overflow-hidden rounded-lg bg-black">
|
||||
<img src="{{ $feat->thumb }}"
|
||||
alt="{{ e($feat->name) }}"
|
||||
class="w-full object-cover transition-transform duration-300 group-hover:scale-105"
|
||||
style="aspect-ratio:4/3;">
|
||||
</div>
|
||||
<h4 class="mt-2 text-sm font-medium text-white truncate">{{ e($feat->name) }}</h4>
|
||||
@if($feat->label)
|
||||
<p class="text-xs text-[--sb-muted]">{{ e($feat->label) }}</p>
|
||||
@endif
|
||||
@if($feat->featured_at)
|
||||
<p class="text-xs text-[--sb-muted] mt-0.5">
|
||||
<i class="fa-solid fa-calendar fa-fw"></i>
|
||||
Featured {{ \Carbon\Carbon::parse($feat->featured_at)->format('d M, Y') }}
|
||||
</p>
|
||||
@endif
|
||||
</a>
|
||||
{{-- Side featured (2nd & 3rd) --}}
|
||||
@if($featuredArtworks->count() > 1)
|
||||
<div class="md:w-44 space-y-2">
|
||||
@foreach($featuredArtworks->slice(1) as $sideArt)
|
||||
<a href="/art/{{ $sideArt->id }}/{{ \Illuminate\Support\Str::slug($sideArt->name) }}"
|
||||
class="block group">
|
||||
<div class="overflow-hidden rounded-md bg-black">
|
||||
<img src="{{ $sideArt->thumb }}"
|
||||
alt="{{ e($sideArt->name) }}"
|
||||
class="w-full object-cover transition-transform duration-300 group-hover:scale-105"
|
||||
style="aspect-ratio:16/9;">
|
||||
</div>
|
||||
<p class="text-xs text-[--sb-muted] mt-1 truncate">{{ e($sideArt->name) }}</p>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Newest Artworks --}}
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-images fa-fw text-[--sb-blue]"></i>
|
||||
Newest Artworks
|
||||
<a href="/gallery/{{ $user->id }}/{{ \Illuminate\Support\Str::slug($uname) }}"
|
||||
class="ml-auto text-xs text-[--sb-blue] hover:underline normal-case tracking-normal font-normal">
|
||||
View Gallery <i class="fa-solid fa-arrow-right fa-fw"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="nova-panel-body">
|
||||
@if(isset($artworks) && !$artworks->isEmpty())
|
||||
<div class="gallery-grid grid grid-cols-2 gap-4"
|
||||
data-nova-gallery
|
||||
data-gallery-type="profile"
|
||||
data-gallery-grid
|
||||
data-profile-id="{{ $user->id }}">
|
||||
@foreach($artworks as $art)
|
||||
<x-artwork-card :art="$art" />
|
||||
@endforeach
|
||||
</div>
|
||||
<div class="hidden" data-gallery-skeleton-template aria-hidden="true">
|
||||
<x-skeleton.artwork-card />
|
||||
</div>
|
||||
<div class="hidden mt-6" data-gallery-skeleton></div>
|
||||
@else
|
||||
<p class="text-[--sb-muted] text-sm text-center py-8">
|
||||
<i class="fa-solid fa-image fa-2x mb-3 block opacity-20"></i>
|
||||
No artworks yet.
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Favourites --}}
|
||||
@if(isset($favourites) && $favourites->isNotEmpty())
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-heart fa-fw text-pink-400"></i>
|
||||
Favourites
|
||||
</div>
|
||||
<div class="nova-panel-body">
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
@foreach($favourites as $fav)
|
||||
<x-artwork-card :art="$fav" />
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>{{-- end left --}}
|
||||
|
||||
{{-- ─── RIGHT SIDEBAR ─── --}}
|
||||
<div class="lg:w-80 xl:w-96 shrink-0 space-y-4">
|
||||
|
||||
{{-- Profile Info --}}
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-id-card fa-fw text-[--sb-blue]"></i>
|
||||
Profile
|
||||
</div>
|
||||
<div class="nova-panel-body">
|
||||
<table class="profile-table w-full">
|
||||
<tr>
|
||||
<td>Username</td>
|
||||
<td>{{ e($uname) }}</td>
|
||||
</tr>
|
||||
@if($displayName && $displayName !== $uname)
|
||||
<tr><td>Real Name</td><td>{{ e($displayName) }}</td></tr>
|
||||
@endif
|
||||
<tr>
|
||||
<td>Gender</td>
|
||||
<td>
|
||||
<i class="fa-solid {{ $gender['icon'] }} fa-fw {{ $gender['color'] }}"></i>
|
||||
{{ $gender['label'] }}
|
||||
</td>
|
||||
</tr>
|
||||
@if($birthdate)
|
||||
<tr><td>Birthday</td><td>{{ $birthdate }}</td></tr>
|
||||
@endif
|
||||
@if($countryName)
|
||||
<tr>
|
||||
<td>Country</td>
|
||||
<td class="flex items-center justify-end gap-1.5">
|
||||
@if($profile?->country_code)
|
||||
<img src="/gfx/flags/shiny/24/{{ rawurlencode($profile->country_code) }}.png"
|
||||
alt="{{ e($countryName) }}"
|
||||
class="w-4 h-auto rounded-sm"
|
||||
onerror="this.style.display='none'">
|
||||
@endif
|
||||
{{ e($countryName) }}
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
@if($website)
|
||||
<tr>
|
||||
<td>Website</td>
|
||||
<td>
|
||||
<a href="{{ e($website) }}" rel="nofollow noopener" target="_blank"
|
||||
class="text-[--sb-blue] hover:underline text-xs inline-flex items-center gap-1">
|
||||
<i class="fa-solid fa-link fa-fw"></i>
|
||||
{{ e(parse_url($website, PHP_URL_HOST) ?? $website) }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
@if($lastVisit)
|
||||
<tr>
|
||||
<td>Last Activity</td>
|
||||
<td class="text-[11px]">
|
||||
{{ $lastVisit->format('d.M.Y') }}
|
||||
<i class="fa-solid fa-clock fa-fw ml-1 opacity-60"></i>
|
||||
{{ $lastVisit->format('H:i') }}
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
<tr>
|
||||
<td>Member since</td>
|
||||
<td>{{ $user->created_at ? $user->created_at->format('M Y') : 'N/A' }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- About Me --}}
|
||||
@if($about)
|
||||
<div class="nova-panel" x-data="{ expanded: false }">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-quote-left fa-fw text-purple-400"></i>
|
||||
About Me
|
||||
</div>
|
||||
<div class="nova-panel-body">
|
||||
<div class="text-sm text-[--sb-text] leading-relaxed"
|
||||
:class="expanded ? '' : 'line-clamp-6'">
|
||||
{!! nl2br(e($about)) !!}
|
||||
</div>
|
||||
@if(strlen($about) > 300)
|
||||
<button @click="expanded = !expanded"
|
||||
class="mt-2 text-xs text-[--sb-blue] hover:underline">
|
||||
<span x-text="expanded ? '↑ Show less' : '↓ Read more'"></span>
|
||||
</button>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Statistics --}}
|
||||
@if($stats)
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-chart-bar fa-fw text-green-400"></i>
|
||||
Statistics
|
||||
</div>
|
||||
<div class="nova-panel-body p-0">
|
||||
<table class="profile-table w-full">
|
||||
@foreach([
|
||||
['Profile Views', number_format($stats->profile_views ?? 0), null],
|
||||
['Uploads', number_format($stats->uploads ?? 0), null],
|
||||
['Downloads', number_format($stats->downloads ?? 0), null],
|
||||
['Page Views', number_format($stats->pageviews ?? 0), null],
|
||||
['Featured Works',number_format($stats->awards ?? 0), 'fa-star text-yellow-400'],
|
||||
] as [$label, $value, $iconClass])
|
||||
<tr>
|
||||
<td class="pl-4">{{ $label }}</td>
|
||||
<td class="pr-4">
|
||||
{{ $value }}
|
||||
@if($iconClass)<i class="fa-solid {{ $iconClass }} text-xs ml-1"></i>@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Social Links --}}
|
||||
@if(isset($socialLinks) && $socialLinks->isNotEmpty())
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-share-nodes fa-fw text-[--sb-blue]"></i>
|
||||
Social Links
|
||||
</div>
|
||||
<div class="nova-panel-body flex flex-wrap gap-2">
|
||||
@foreach($socialLinks as $platform => $link)
|
||||
@php
|
||||
$si = $socialIcons[$platform] ?? ['icon' => 'fa-solid fa-link', 'label' => ucfirst($platform)];
|
||||
$href = str_starts_with($link->url, 'http') ? $link->url : ('https://' . $link->url);
|
||||
@endphp
|
||||
<a href="{{ e($href) }}" rel="nofollow noopener" target="_blank"
|
||||
class="inline-flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg text-xs border border-[--sb-line] text-[--sb-text] hover:bg-white/5 hover:border-[--sb-blue]/40 transition-all">
|
||||
<i class="{{ $si['icon'] }} fa-fw"></i>
|
||||
{{ $si['label'] }}
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Recent Followers --}}
|
||||
@if(isset($recentFollowers) && $recentFollowers->isNotEmpty())
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-users fa-fw text-[--sb-blue]"></i>
|
||||
Followers
|
||||
<span class="ml-1 px-1.5 py-0.5 rounded text-xs bg-white/5 text-[--sb-muted]">
|
||||
{{ number_format($followerCount) }}
|
||||
</span>
|
||||
<a href="/following/{{ $user->id }}/{{ \Illuminate\Support\Str::slug($uname) }}"
|
||||
class="ml-auto text-xs text-[--sb-blue] hover:underline normal-case tracking-normal font-normal">
|
||||
All
|
||||
</a>
|
||||
</div>
|
||||
<div class="nova-panel-body">
|
||||
<div class="flex flex-wrap gap-1.5">
|
||||
@foreach($recentFollowers as $follower)
|
||||
<a href="{{ $follower->profile_url }}" title="{{ e($follower->uname) }}">
|
||||
<img src="{{ $follower->avatar_url }}"
|
||||
alt="{{ e($follower->uname) }}"
|
||||
class="follower-avatar"
|
||||
onerror="this.src='{{ \App\Support\AvatarUrl::default() }}'">
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@elseif($followerCount > 0)
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-users fa-fw text-[--sb-blue]"></i>
|
||||
Followers
|
||||
<span class="ml-1 px-1.5 py-0.5 rounded text-xs bg-white/5 text-[--sb-muted]">
|
||||
{{ number_format($followerCount) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Profile Comments --}}
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-comments fa-fw text-orange-400"></i>
|
||||
Comments
|
||||
@if(isset($profileComments) && $profileComments->isNotEmpty())
|
||||
<span class="ml-1 px-1.5 py-0.5 rounded text-xs bg-white/5 text-[--sb-muted]">
|
||||
{{ $profileComments->count() }}
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
<div class="nova-panel-body">
|
||||
@if(!isset($profileComments) || $profileComments->isEmpty())
|
||||
<p class="text-[--sb-muted] text-xs text-center py-3">No comments yet.</p>
|
||||
@else
|
||||
<div class="space-y-4">
|
||||
@foreach($profileComments as $comment)
|
||||
<div class="flex gap-3">
|
||||
<a href="{{ $comment->author_profile_url }}" class="shrink-0">
|
||||
<img src="{{ $comment->author_avatar }}"
|
||||
alt="{{ e($comment->author_name) }}"
|
||||
class="comment-avatar"
|
||||
onerror="this.src='{{ \App\Support\AvatarUrl::default() }}'">
|
||||
</a>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-2 mb-1">
|
||||
<a href="{{ $comment->author_profile_url }}"
|
||||
class="text-xs font-semibold text-[--sb-text] hover:text-[--sb-blue] transition-colors">
|
||||
{{ e($comment->author_name) }}
|
||||
</a>
|
||||
<span class="text-[--sb-muted] text-[10px] ml-auto whitespace-nowrap">
|
||||
{{ \Carbon\Carbon::parse($comment->created_at)->diffForHumans() }}
|
||||
</span>
|
||||
</div>
|
||||
<p class="text-xs text-[--sb-text] leading-relaxed break-words">
|
||||
{!! nl2br(e($comment->body)) !!}
|
||||
</p>
|
||||
@if(!empty($comment->author_signature))
|
||||
<p class="text-[--sb-muted] text-[10px] mt-1 italic border-t border-[--sb-line] pt-1 opacity-70">
|
||||
{!! nl2br(e($comment->author_signature)) !!}
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Write Comment --}}
|
||||
@auth
|
||||
@if(auth()->id() !== $user->id)
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-pen fa-fw text-[--sb-blue]"></i>
|
||||
Write a Comment
|
||||
</div>
|
||||
<div class="nova-panel-body">
|
||||
@if(session('status') === 'Comment posted!')
|
||||
<div class="mb-3 px-3 py-2 rounded-lg bg-green-500/10 border border-green-500/30 text-green-400 text-xs">
|
||||
<i class="fa-solid fa-check fa-fw"></i> Comment posted!
|
||||
</div>
|
||||
@endif
|
||||
<form method="POST"
|
||||
action="{{ route('profile.comment', ['username' => strtolower((string)$uname)]) }}">
|
||||
@csrf
|
||||
<textarea name="body" rows="4" required minlength="2" maxlength="2000"
|
||||
placeholder="Write a comment for {{ e($uname) }}..."
|
||||
class="w-full bg-[--sb-bg] border border-[--sb-line] rounded-lg px-3 py-2 text-sm text-[--sb-text] placeholder:text-[--sb-muted]/60 resize-none focus:outline-none focus:border-[--sb-blue]/50 transition-colors"
|
||||
>{{ old('body') }}</textarea>
|
||||
@error('body')
|
||||
<p class="mt-1 text-xs text-red-400">{{ $message }}</p>
|
||||
@enderror
|
||||
<div class="mt-2 text-right">
|
||||
<button type="submit"
|
||||
class="inline-flex items-center gap-1.5 px-4 py-2 rounded-lg text-sm font-medium bg-[--sb-blue]/90 hover:bg-[--sb-blue] text-white transition-colors">
|
||||
<i class="fa-solid fa-paper-plane fa-fw"></i>
|
||||
Post Comment
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@else
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-body text-center py-4">
|
||||
<p class="text-[--sb-muted] text-sm">
|
||||
<a href="{{ route('login') }}" class="text-[--sb-blue] hover:underline">Log in</a>
|
||||
to leave a comment.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@endauth
|
||||
|
||||
</div>{{-- end right sidebar --}}
|
||||
|
||||
</div>{{-- end flex --}}
|
||||
</div>{{-- end container --}}
|
||||
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script src="/js/legacy-gallery-init.js" defer></script>
|
||||
@endpush
|
||||
63
resources/views/_legacy/received-comments.blade.php
Normal file
63
resources/views/_legacy/received-comments.blade.php
Normal file
@@ -0,0 +1,63 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid legacy-page">
|
||||
<div class="effect2 page-header-wrap">
|
||||
<header class="page-heading">
|
||||
<h1 class="page-header">Received Comments</h1>
|
||||
<p>List of comments left on your uploaded artworks.</p>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<div class="masonry">
|
||||
@foreach($comments as $comment)
|
||||
@php
|
||||
$author = $comment->user;
|
||||
$art = $comment->artwork;
|
||||
$created = optional($comment->created_at);
|
||||
@endphp
|
||||
|
||||
<div class="masonry_item col-sm-6 col-md-4">
|
||||
<div class="comment_box effect3">
|
||||
<div class="cb_image">
|
||||
<a href="/profile/{{ (int)($author->id ?? $author->user_id) }}/{{ rawurlencode($author->name ?? $author->uname ?? '') }}">
|
||||
<img src="{{ \App\Support\AvatarUrl::forUser((int) ($author->id ?? $author->user_id), null, 50) }}" width="50" height="50" class="comment_avatar" alt="{{ $author->name ?? $author->uname ?? '' }}">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="bubble_comment panel panel-skinbase">
|
||||
<div class="panel-heading">
|
||||
<div class="pull-right">{{ $created ? $created->diffForHumans() . ' ago' : '' }}</div>
|
||||
<h5 class="panel-title">Comment by: <a href="/profile/{{ (int)($author->id ?? $author->user_id) }}/{{ rawurlencode($author->name ?? $author->uname ?? '') }}">{{ $author->name ?? $author->uname ?? '' }}</a></h5>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="comment_box_image">
|
||||
@if($art)
|
||||
<a href="/art/{{ $art->id }}/{{ Str::slug($art->name ?? '') }}">
|
||||
<img src="{{ $art->thumb }}" class="img-thumbnail img-responsive" alt="{{ $art->name }}">
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="comment_text">{!! nl2br(e($comment->content ?? $comment->description ?? '')) !!}</div>
|
||||
|
||||
@if(!empty($author->signature))
|
||||
<div class="panel-footer comment-footer">
|
||||
<p>{!! nl2br(e($author->signature)) !!}</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
@if($comments->hasPages())
|
||||
<div class="paginationMenu">
|
||||
{{ $comments->links() }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
@endsection
|
||||
81
resources/views/_legacy/statistics.blade.php
Normal file
81
resources/views/_legacy/statistics.blade.php
Normal file
@@ -0,0 +1,81 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
<div class="container legacy-page">
|
||||
<div class="page-header-wrap">
|
||||
<div class="clearfix">
|
||||
<h1 class="page-header" style="margin:0;display:inline-block">Artwork Statistics</h1>
|
||||
<span class="text-muted pull-right" style="margin-top:10px">
|
||||
Uploaded: {{ method_exists($artworks, 'total') ? $artworks->total() : $artworks->count() }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-muted" style="margin-top:6px;font-size:12px">Sort your uploads by popularity, downloads, comments, and date.</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default uploads-panel">
|
||||
<div class="panel-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered table-striped table-hover" style="margin-bottom:0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:90px" class="text-center">Thumbnail</th>
|
||||
<th>
|
||||
<a href="{{ request()->fullUrlWithQuery(['sort' => 'name']) }}">Name</a>
|
||||
</th>
|
||||
<th style="width:110px" class="text-center">
|
||||
<a href="{{ request()->fullUrlWithQuery(['sort' => 'dls']) }}">Downloads</a>
|
||||
</th>
|
||||
<th style="width:95px" class="text-center">
|
||||
<a href="{{ request()->fullUrlWithQuery(['sort' => 'comments']) }}">Reviews</a>
|
||||
</th>
|
||||
<th style="width:180px">
|
||||
<a href="{{ request()->fullUrlWithQuery(['sort' => 'category']) }}">Section</a>
|
||||
</th>
|
||||
<th style="width:130px" class="text-center">
|
||||
<a href="{{ request()->fullUrlWithQuery(['sort' => 'date']) }}">Date</a>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($artworks as $art)
|
||||
<tr>
|
||||
<td class="text-center">
|
||||
<a href="/art/{{ (int) $art->id }}" title="View">
|
||||
<img
|
||||
src="{{ $art->thumb_url ?? '/gfx/sb_join.jpg' }}"
|
||||
@if(!empty($art->thumb_srcset)) srcset="{{ $art->thumb_srcset }}" @endif
|
||||
alt="{{ $art->name ?? '' }}"
|
||||
class="img-thumbnail"
|
||||
style="width:70px;height:70px;object-fit:cover"
|
||||
>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="/art/{{ (int) $art->id }}">{{ $art->name ?? '' }}</a>
|
||||
<div class="text-muted" style="font-size:12px">#{{ (int) $art->id }}</div>
|
||||
</td>
|
||||
<td class="text-center">{{ (int) ($art->dls ?? 0) }}</td>
|
||||
<td class="text-center">{{ (int) ($art->num_comments ?? 0) }}</td>
|
||||
<td>{{ $art->category_name ?? '' }}</td>
|
||||
<td class="text-center">
|
||||
@if(!empty($art->datum))
|
||||
{{ is_string($art->datum) ? date('d.m.Y', strtotime($art->datum)) : '' }}
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="6">No artworks found.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="paginationMenu text-center">
|
||||
{{ $artworks->links('pagination::bootstrap-3') }}
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
34
resources/views/_legacy/today-in-history.blade.php
Normal file
34
resources/views/_legacy/today-in-history.blade.php
Normal file
@@ -0,0 +1,34 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid legacy-page">
|
||||
<div class="effect2 page-header-wrap">
|
||||
<header class="page-heading">
|
||||
<h1 class="page-header">{{ $page_title ?? 'Today in History' }}</h1>
|
||||
<p>List of featured Artworks on this day in history of Skinbase.</p>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default uploads-panel effect2">
|
||||
<div class="panel-body">
|
||||
<div class="container_photo gallery_box">
|
||||
@if($artworks && $artworks->count())
|
||||
@foreach($artworks as $ar)
|
||||
<div class="photo_frame">
|
||||
<a href="/art/{{ $ar->id }}/{{ \Illuminate\Support\Str::slug($ar->name ?? '') }}">
|
||||
<img src="{{ $ar->thumb_url ?? '/gfx/sb_join.jpg' }}" @if(!empty($ar->thumb_srcset)) srcset="{{ $ar->thumb_srcset }}" @endif loading="lazy" decoding="async" alt="{{ $ar->name }}">
|
||||
</a>
|
||||
</div>
|
||||
@endforeach
|
||||
@else
|
||||
<p class="text-muted">No featured artworks found for today in history.</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="paginationMenu text-center">
|
||||
@if($artworks){{ $artworks->withQueryString()->links('pagination::bootstrap-4') }}@endif
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
117
resources/views/_legacy/top-authors.blade.php
Normal file
117
resources/views/_legacy/top-authors.blade.php
Normal file
@@ -0,0 +1,117 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid legacy-page">
|
||||
<div class="effect2 page-header-wrap">
|
||||
<header class="page-heading">
|
||||
<h1 class="page-header">Top Members</h1>
|
||||
<p>Statistics of popular and active members at Skinbase</p>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-default effect2">
|
||||
<div class="panel-heading"><strong>Most Active Members</strong></div>
|
||||
<div class="panel-body">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="2">Username</th>
|
||||
<th class="text-right">Uploads</th>
|
||||
<th class="text-right">Total Downloads</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($topUsers as $u)
|
||||
<tr>
|
||||
<td width="80">
|
||||
<a href="/profile/{{ $u->user_id }}/{{ \Illuminate\Support\Str::slug($u->uname) }}">
|
||||
<img src="{{ \App\Support\AvatarUrl::forUser((int) $u->user_id, null, 32) }}" width="30" height="30" alt="{{ $u->uname }}">
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="/profile/{{ $u->user_id }}/{{ \Illuminate\Support\Str::slug($u->uname) }}">{{ $u->uname }}</a>
|
||||
</td>
|
||||
<td class="text-right">{{ $u->uploads }}</td>
|
||||
<td class="text-right">{{ $u->total_downloads }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-default effect2">
|
||||
<div class="panel-heading"><strong>Most Followed Members</strong></div>
|
||||
<div class="panel-body">
|
||||
<table class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Thumb</th>
|
||||
<th>Name</th>
|
||||
<th>Followers</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($topFollowers as $f)
|
||||
<tr>
|
||||
<td width="60" align="center">
|
||||
<a href="/profile/{{ $f->user_id }}/{{ \Illuminate\Support\Str::slug($f->uname) }}">
|
||||
<img src="{{ \App\Support\AvatarUrl::forUser((int) $f->user_id, null, 32) }}" width="30" alt="{{ $f->uname }}">
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="/profile/{{ $f->user_id }}/{{ \Illuminate\Support\Str::slug($f->uname) }}">{{ $f->uname }}</a>
|
||||
</td>
|
||||
<td align="center">{{ $f->num }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default effect2">
|
||||
<div class="panel-heading"><strong>Top Commentators</strong></div>
|
||||
<div class="panel-body">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Thumb</th>
|
||||
<th>Name</th>
|
||||
<th>Level</th>
|
||||
<th>Country</th>
|
||||
<th>Comments</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($topCommentators as $c)
|
||||
<tr>
|
||||
<td width="50" align="center">
|
||||
<a href="/profile/{{ $c->user_id }}/{{ \Illuminate\Support\Str::slug($c->uname) }}">
|
||||
<img src="{{ \App\Support\AvatarUrl::forUser((int) $c->user_id, null, 32) }}" width="30" alt="{{ $c->uname }}">
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="/profile/{{ $c->user_id }}/{{ \Illuminate\Support\Str::slug($c->uname) }}">{{ $c->uname }}</a>
|
||||
</td>
|
||||
<td width="100" align="center"><img src="/gfx/member_stars/{{ $c->user_type }}.gif" alt="level"></td>
|
||||
<td width="100" align="center">
|
||||
@if(!empty($c->country_flag))
|
||||
<img width="20" src="/gfx/flags/{{ rawurlencode($c->country_flag) }}" title="{{ $c->country_name }}">
|
||||
@endif
|
||||
</td>
|
||||
<td width="100" align="center">{{ $c->num_comments }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
32
resources/views/_legacy/top-favourites.blade.php
Normal file
32
resources/views/_legacy/top-favourites.blade.php
Normal file
@@ -0,0 +1,32 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid legacy-page">
|
||||
<div class="effect2 page-header-wrap">
|
||||
<header class="page-heading">
|
||||
<h1 class="page-header">{{ $page_title }}</h1>
|
||||
<p>Most popular artworks which users added in their favourites</p>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
@if ($artworks && $artworks->count())
|
||||
<div class="container_photo gallery_box">
|
||||
<div class="grid-sizer"></div>
|
||||
@foreach ($artworks as $art)
|
||||
@include('legacy::_artwork_card', ['art' => $art])
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="paginationMenu text-center">
|
||||
{{ $artworks->withQueryString()->links('pagination::bootstrap-4') }}
|
||||
</div>
|
||||
@else
|
||||
<div class="panel panel-default effect2">
|
||||
<div class="panel-heading"><strong>No Artworks Yet</strong></div>
|
||||
<div class="panel-body">
|
||||
<p>Once uploads arrive they will appear here. Check back soon.</p>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endsection
|
||||
368
resources/views/_legacy/user.blade.php
Normal file
368
resources/views/_legacy/user.blade.php
Normal file
@@ -0,0 +1,368 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
|
||||
@php
|
||||
$birthDay = $birthDay ?? null;
|
||||
$birthMonth = $birthMonth ?? null;
|
||||
$birthYear = $birthYear ?? null;
|
||||
$avatarUserId = (int) ($user->id ?? auth()->id() ?? 0);
|
||||
$avatarHash = $user->icon
|
||||
?? optional(auth()->user())->profile->avatar_hash
|
||||
?? null;
|
||||
$currentAvatarUrl = !empty($avatarHash)
|
||||
? \App\Support\AvatarUrl::forUser($avatarUserId, $avatarHash, 128)
|
||||
: \App\Support\AvatarUrl::default();
|
||||
@endphp
|
||||
|
||||
@push('styles')
|
||||
<style>
|
||||
.edit-profile-hero { position: relative; overflow: hidden; }
|
||||
</style>
|
||||
@endpush
|
||||
|
||||
{{-- ── Hero background ──────────────────────────────────────────────── --}}
|
||||
<div class="edit-profile-hero border-b border-[--sb-line]"
|
||||
@if(!empty($heroBgUrl))
|
||||
style="background: url('{{ $heroBgUrl }}') center/cover no-repeat;"
|
||||
@else
|
||||
style="background: linear-gradient(135deg, rgba(15,23,36,1) 0%, rgba(21,30,46,1) 50%, rgba(9,16,26,1) 100%);"
|
||||
@endif
|
||||
>
|
||||
@if(!empty($heroBgUrl))
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-[#0f1724]/95 via-[#0f1724]/80 to-[#0f1724]/50"></div>
|
||||
@endif
|
||||
<div class="relative z-10 max-w-5xl mx-auto px-4 py-10 flex items-end gap-5">
|
||||
<img src="{{ $currentAvatarUrl }}"
|
||||
alt="Your avatar"
|
||||
class="w-20 h-20 rounded-full object-cover border-4 border-[--sb-line] shadow-lg shrink-0">
|
||||
<div>
|
||||
<h1 class="text-2xl font-bold text-white">Edit Profile</h1>
|
||||
<p class="text-sm text-[--sb-muted] mt-1">Manage your account settings</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="min-h-screen text-white py-12">
|
||||
|
||||
<!-- Container -->
|
||||
<div class="max-w-5xl mx-auto px-4">
|
||||
|
||||
@if ($errors->any())
|
||||
<div class="mb-4 rounded-lg bg-red-700/10 border border-red-700/20 p-3 text-sm text-red-300">
|
||||
<div class="font-semibold mb-2">Please fix the following errors:</div>
|
||||
<ul class="list-disc pl-5 space-y-1">
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<!-- ================= Profile Card ================= -->
|
||||
<div class="bg-nova-800 rounded-xl shadow-lg p-8 mb-10">
|
||||
|
||||
<form method="POST" action="{{ route('profile.update') }}" enctype="multipart/form-data">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
|
||||
<!-- LEFT COLUMN -->
|
||||
<div class="space-y-5">
|
||||
|
||||
<!-- Email -->
|
||||
<div>
|
||||
<label class="form-label">Email</label>
|
||||
<input type="email" name="email"
|
||||
class="form-input"
|
||||
value="{{ old('email', auth()->user()->email) }}">
|
||||
</div>
|
||||
|
||||
<!-- Username -->
|
||||
<div>
|
||||
<label class="form-label">Username</label>
|
||||
<input type="text" name="username"
|
||||
class="form-input"
|
||||
value="{{ old('username', auth()->user()->username) }}"
|
||||
readonly>
|
||||
</div>
|
||||
|
||||
<!-- Real Name -->
|
||||
<div>
|
||||
<label class="form-label">Real Name</label>
|
||||
<input type="text" name="name"
|
||||
class="form-input"
|
||||
value="{{ old('name', auth()->user()->name) }}">
|
||||
</div>
|
||||
|
||||
<!-- Homepage -->
|
||||
<div>
|
||||
<label class="form-label">Homepage</label>
|
||||
<input type="url" name="homepage"
|
||||
class="form-input"
|
||||
placeholder="https://"
|
||||
value="{{ old('homepage', auth()->user()->homepage ?? auth()->user()->website ?? '') }}">
|
||||
</div>
|
||||
|
||||
<!-- Birthday -->
|
||||
<div>
|
||||
<label class="form-label">Birthday</label>
|
||||
|
||||
<div class="grid grid-cols-3 gap-3">
|
||||
@php
|
||||
$currentYear = date('Y');
|
||||
$startYear = $currentYear - 100;
|
||||
$months = ['January','February','March','April','May','June','July','August','September','October','November','December'];
|
||||
@endphp
|
||||
|
||||
<select name="day" class="form-input" aria-label="Day">
|
||||
<option value="">Day</option>
|
||||
@for($d = 1; $d <= 31; $d++)
|
||||
<option value="{{ $d }}" @if(intval(old('day', $birthDay)) == $d) selected @endif>{{ $d }}</option>
|
||||
@endfor
|
||||
</select>
|
||||
|
||||
<select name="month" class="form-input" aria-label="Month">
|
||||
<option value="">Month</option>
|
||||
@foreach($months as $idx => $m)
|
||||
@php $val = $idx + 1; @endphp
|
||||
<option value="{{ $val }}" @if(intval(old('month', $birthMonth)) == $val) selected @endif>{{ $m }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<select name="year" class="form-input" aria-label="Year">
|
||||
<option value="">Year</option>
|
||||
@for($y = $currentYear; $y >= $startYear; $y--)
|
||||
<option value="{{ $y }}" @if(intval(old('year', $birthYear)) == $y) selected @endif>{{ $y }}</option>
|
||||
@endfor
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gender -->
|
||||
<div>
|
||||
<label class="form-label">Gender</label>
|
||||
|
||||
<div class="flex gap-6 mt-2 text-soft">
|
||||
<label><input type="radio" name="gender" value="m" @if(old('gender', strtolower(auth()->user()->gender ?? '')) == 'm') checked @endif> Male</label>
|
||||
<label><input type="radio" name="gender" value="f" @if(old('gender', strtolower(auth()->user()->gender ?? '')) == 'f') checked @endif> Female</label>
|
||||
<label><input type="radio" name="gender" value="x" @if(old('gender', strtolower(auth()->user()->gender ?? '')) == 'x') checked @endif> N/A</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Country -->
|
||||
<div>
|
||||
<label class="form-label">Country</label>
|
||||
<input type="text" name="country"
|
||||
class="form-input"
|
||||
value="{{ old('country', auth()->user()->country ?? auth()->user()->country_code ?? '') }}">
|
||||
</div>
|
||||
|
||||
<!-- Preferences -->
|
||||
<div class="flex gap-6 text-soft">
|
||||
<label>
|
||||
<input type="checkbox" name="mailing" @if(old('mailing', auth()->user()->mlist ?? false)) checked @endif>
|
||||
Mailing List
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<input type="checkbox" name="notify" @if(old('notify', auth()->user()->friend_upload_notice ?? false)) checked @endif>
|
||||
Upload Notifications
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!-- RIGHT COLUMN -->
|
||||
<div class="space-y-5">
|
||||
|
||||
<!-- Avatar -->
|
||||
<div>
|
||||
<label class="form-label">Avatar</label>
|
||||
<div class="rounded-xl border border-sb-line bg-black/10 p-4">
|
||||
<div class="flex items-center gap-4">
|
||||
<img
|
||||
id="avatarPreviewImage"
|
||||
src="{{ $currentAvatarUrl }}"
|
||||
alt="{{ $user->name ?? $user->username ?? 'Avatar' }}"
|
||||
class="w-24 h-24 rounded-full object-cover ring-1 ring-white/10"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
>
|
||||
<div class="min-w-0 flex-1">
|
||||
<button
|
||||
type="button"
|
||||
id="avatarDropzone"
|
||||
class="w-full rounded-lg border border-dashed border-sb-line px-4 py-4 text-left hover:bg-white/5 focus:outline-none focus:ring-2 focus:ring-sb-blue/50"
|
||||
>
|
||||
<div class="text-sm text-white/90">Drag & drop a new avatar here</div>
|
||||
<div class="text-xs text-soft mt-1">or click to browse (JPG, PNG, WEBP)</div>
|
||||
<div id="avatarFileName" class="text-xs text-sb-muted mt-2 truncate">No file selected</div>
|
||||
</button>
|
||||
<input id="avatarInput" type="file" name="avatar" class="sr-only" accept="image/jpeg,image/png,image/webp">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Emoticon -->
|
||||
<div>
|
||||
<label class="form-label">Emoticon</label>
|
||||
<input type="file" name="emoticon" class="form-file">
|
||||
</div>
|
||||
|
||||
<!-- Personal Picture -->
|
||||
<div>
|
||||
<label class="form-label">Personal Picture</label>
|
||||
<input type="file" name="photo" class="form-file">
|
||||
</div>
|
||||
|
||||
<!-- About -->
|
||||
<div>
|
||||
<label class="form-label">About Me</label>
|
||||
<textarea name="about" rows="4"
|
||||
class="form-textarea">{{ old('about', auth()->user()->about ?? auth()->user()->about_me ?? '') }}</textarea>
|
||||
</div>
|
||||
|
||||
<!-- Signature -->
|
||||
<div>
|
||||
<label class="form-label">Signature</label>
|
||||
<textarea name="signature" rows="3"
|
||||
class="form-textarea">{{ old('signature', auth()->user()->signature ?? '') }}</textarea>
|
||||
</div>
|
||||
|
||||
<!-- Description -->
|
||||
<div>
|
||||
<label class="form-label">Description</label>
|
||||
<textarea name="description" rows="4"
|
||||
class="form-textarea">{{ old('description', auth()->user()->description ?? '') }}</textarea>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Save Button -->
|
||||
<div class="mt-8 text-right">
|
||||
<button type="submit"
|
||||
class="btn-primary">
|
||||
Update Profile
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!-- ================= PASSWORD CARD ================= -->
|
||||
<div class="bg-nova-800 rounded-xl shadow-lg p-8">
|
||||
|
||||
<h2 class="text-xl font-semibold mb-6">
|
||||
Change Password
|
||||
</h2>
|
||||
|
||||
<form method="POST" action="{{ route('profile.password') }}">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="space-y-5 max-w-md">
|
||||
|
||||
<div>
|
||||
<label class="form-label">Current Password</label>
|
||||
<input type="password" name="current_password"
|
||||
class="form-input">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="form-label">New Password</label>
|
||||
<input type="password" name="password"
|
||||
class="form-input">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="form-label">Repeat Password</label>
|
||||
<input type="password" name="password_confirmation"
|
||||
class="form-input">
|
||||
</div>
|
||||
|
||||
<button class="btn-secondary">
|
||||
Change Password
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
(() => {
|
||||
const input = document.getElementById('avatarInput');
|
||||
const dropzone = document.getElementById('avatarDropzone');
|
||||
const preview = document.getElementById('avatarPreviewImage');
|
||||
const fileName = document.getElementById('avatarFileName');
|
||||
if (!input || !dropzone || !preview || !fileName) {
|
||||
return;
|
||||
}
|
||||
|
||||
const updatePreview = (file) => {
|
||||
if (!file || !file.type || !file.type.startsWith('image/')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const objectUrl = URL.createObjectURL(file);
|
||||
preview.src = objectUrl;
|
||||
fileName.textContent = file.name;
|
||||
preview.onload = () => URL.revokeObjectURL(objectUrl);
|
||||
};
|
||||
|
||||
dropzone.addEventListener('click', () => input.click());
|
||||
|
||||
input.addEventListener('change', () => {
|
||||
const file = input.files && input.files[0] ? input.files[0] : null;
|
||||
if (file) {
|
||||
updatePreview(file);
|
||||
}
|
||||
});
|
||||
|
||||
['dragenter', 'dragover'].forEach((eventName) => {
|
||||
dropzone.addEventListener(eventName, (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
dropzone.classList.add('ring-2', 'ring-sb-blue/50');
|
||||
});
|
||||
});
|
||||
|
||||
['dragleave', 'drop'].forEach((eventName) => {
|
||||
dropzone.addEventListener(eventName, (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
dropzone.classList.remove('ring-2', 'ring-sb-blue/50');
|
||||
});
|
||||
});
|
||||
|
||||
dropzone.addEventListener('drop', (event) => {
|
||||
const file = event.dataTransfer && event.dataTransfer.files ? event.dataTransfer.files[0] : null;
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
|
||||
const dt = new DataTransfer();
|
||||
dt.items.add(file);
|
||||
input.files = dt.files;
|
||||
updatePreview(file);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
@endpush
|
||||
Reference in New Issue
Block a user