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:
2026-02-26 10:25:35 +01:00
parent d3fd32b004
commit d0aefc5ddc
78 changed files with 1046 additions and 221 deletions

View File

@@ -0,0 +1,2 @@
{{-- Shim for legacy artwork card includes. Points to new web partial. --}}
@include('web.partials._artwork_card')

View 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> &nbsp; Photography</a></li>
<li><a href="/wallpapers"><i class="fa fa-desktop"></i> &nbsp; Wallpapers</a></li>
<li><a href="/skins"><i class="fa fa-eye"></i> &nbsp; Skins</a></li>
<li><a href="/other"><i class="fa fa-file-o"></i> &nbsp; Others</a></li>
<li role="separator" class="divider"></li>
<li><a href="/browse-categories" class="btn_category"><i class="fa fa-list"></i> &nbsp; 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">&nbsp;&nbsp;
<span class="username">{{ $displayName }}</span>
&nbsp;<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>

View 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

View 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>

View 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&apos;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>

View 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 -->

View 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">&nbsp;{{ $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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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